// ─── Mockup components: all CSS/SVG, resolution-independent ───────

// CharacterMap — 품 관계도
const characters = [
  { id: 'gangeon',    name: '강건',   role: '주인공',      x: 400, y: 310, major: true,  group: 'police',    initial: '강' },
  { id: 'ichanghyun', name: '이창현', role: '정치가',      x: 150, y: 280, major: true,  group: 'politics',  initial: '이' },
  { id: 'chasuyeon',  name: '차수연', role: '협력자',      x: 610, y: 200, major: true,  group: 'influencer',initial: '차' },
  { id: 'juhwajin',   name: '주화진', role: '재단 이사',   x: 610, y: 410, major: true,  group: 'foundation',initial: '주' },
  { id: 'kangtaesik', name: '강태식', role: '부친',        x: 400, y: 140, major: true,  group: 'police',    ghost: true, initial: '태' },
  { id: 'somi',       name: '진소미',                     x: 290, y: 95,  major: false, group: 'family', ghost: true },
  { id: 'chungjae',   name: '석충재',                     x: 70,  y: 390, major: false, group: 'politics' },
  { id: 'choi',       name: '최힘찬',                     x: 300, y: 440, major: false, group: 'police' },
  { id: 'huh',        name: '허병호',                     x: 490, y: 455, major: false, group: 'police' },
];

const cmEdges = [
  { from: 'gangeon', to: 'kangtaesik', label: '부자',     type: 'family' },
  { from: 'gangeon', to: 'ichanghyun', label: '적대',     type: 'enemy', dashed: true },
  { from: 'gangeon', to: 'chasuyeon',  label: '협력',     type: 'ally' },
  { from: 'gangeon', to: 'juhwajin',   label: '후원',     type: 'neutral' },
  { from: 'gangeon', to: 'choi',       label: '상사',     type: 'neutral' },
  { from: 'gangeon', to: 'huh',        label: '동료',     type: 'neutral' },
  { from: 'kangtaesik', to: 'somi',    label: '부부',     type: 'family' },
  { from: 'ichanghyun', to: 'chungjae',label: '측근',     type: 'enemy' },
  { from: 'ichanghyun', to: 'kangtaesik', label: '??',    type: 'enemy', dashed: true },
];

const cmGroups = [
  { id: 'police',     label: '왕주 강력계',      x: 230, y: 250, w: 350, h: 260 },
  { id: 'politics',   label: '정치·권력 세계',   x: 20,  y: 220, w: 210, h: 220 },
  { id: 'influencer', label: '언론·인플루언서',  x: 510, y: 150, w: 190, h: 120 },
  { id: 'foundation', label: '기업·경제권',      x: 510, y: 370, w: 190, h: 130 },
];

const edgeColors = { family: '#f59e0b', enemy: '#ef4444', ally: '#10b981', neutral: '#64748b' };
const groupColors = {
  police:     { fill: 'rgba(34,211,238,0.06)',  stroke: 'rgba(34,211,238,0.25)' },
  politics:   { fill: 'rgba(239,68,68,0.06)',   stroke: 'rgba(239,68,68,0.25)' },
  influencer: { fill: 'rgba(16,185,129,0.06)',  stroke: 'rgba(16,185,129,0.25)' },
  foundation: { fill: 'rgba(192,132,252,0.06)', stroke: 'rgba(192,132,252,0.25)' },
};
const avatarColors = {
  gangeon:    '#22d3ee', ichanghyun: '#f87171', chasuyeon:  '#34d399',
  juhwajin:   '#c084fc', kangtaesik: '#94a3b8',
};

function CharacterMap({ accent = '#22d3ee' }) {
  const [hovered, setHovered] = React.useState(null);
  const lookup = (id) => characters.find(c => c.id === id);
  const isConnected = (id) => !hovered || hovered === id || cmEdges.some(e => (e.from===hovered&&e.to===id)||(e.to===hovered&&e.from===id));
  const isEdgeActive = (e) => !hovered || e.from===hovered || e.to===hovered;

  return (
    <div className="w-full relative bg-[#0d1117] rounded-xl overflow-hidden border border-white/10">
      <div className="px-4 py-2.5 flex items-center justify-between border-b border-white/5 bg-black/30">
        <div className="flex items-center gap-3">
          <span className="text-sm font-semibold text-neutral-200">인물 관계도</span>
          <span className="text-[10px] text-neutral-500">자동 생성 · 방금 전</span>
        </div>
        <div className="flex items-center gap-2 text-[10px]">
          <span className="px-2 py-0.5 rounded border border-white/10 text-neutral-400">PNG 저장</span>
          <span className="px-2 py-0.5 rounded font-medium text-black" style={{background: accent}}>관계도 생성</span>
        </div>
      </div>

      <div className="px-4 py-2 flex items-center gap-3 text-[10px] text-neutral-500 border-b border-white/5 flex-wrap">
        <span className="flex items-center gap-1"><span className="w-1.5 h-1.5 rounded-full" style={{background: accent}} />주연</span>
        <span className="flex items-center gap-1"><span className="w-1.5 h-1.5 rounded-full bg-neutral-500" />조연</span>
        <span className="mx-1 text-neutral-700">|</span>
        <span className="flex items-center gap-1"><span className="w-3 h-px bg-[#ef4444]" />적대</span>
        <span className="flex items-center gap-1"><span className="w-3 h-px bg-[#10b981]" />협력</span>
        <span className="flex items-center gap-1"><span className="w-3 h-px bg-[#f59e0b]" />가족</span>
      </div>

      <svg viewBox="0 0 720 530" className="w-full h-auto block" preserveAspectRatio="xMidYMid meet" onMouseLeave={()=>setHovered(null)}>
        <defs>
          <pattern id="cm-grid" width="24" height="24" patternUnits="userSpaceOnUse">
            <path d="M24 0H0V24" fill="none" stroke="rgba(255,255,255,0.025)" strokeWidth="1"/>
          </pattern>
        </defs>
        <rect width="720" height="530" fill="url(#cm-grid)"/>
        {cmGroups.map(g => {
          const color = groupColors[g.id];
          return (
            <g key={g.id}>
              <rect x={g.x} y={g.y} width={g.w} height={g.h} rx={12} ry={12} fill={color.fill} stroke={color.stroke} strokeWidth={1}/>
              <text x={g.x + 12} y={g.y + 20} fontSize={11} fill="rgba(255,255,255,0.5)">{g.label}</text>
            </g>
          );
        })}
        {cmEdges.map((e, i) => {
          const from = lookup(e.from), to = lookup(e.to); if (!from||!to) return null;
          const midX = (from.x+to.x)/2, midY = (from.y+to.y)/2;
          return (
            <g key={i} style={{opacity: isEdgeActive(e)?1:0.12, transition:'opacity 200ms'}}>
              <line x1={from.x} y1={from.y} x2={to.x} y2={to.y} stroke={edgeColors[e.type]} strokeWidth={1.5} strokeDasharray={e.dashed?'5 4':undefined} opacity={0.8}/>
              <text x={midX} y={midY-5} fontSize={10} fill="#cbd5e1" textAnchor="middle" style={{paintOrder:'stroke', stroke:'#0d1117', strokeWidth:3, strokeLinejoin:'round'}}>{e.label}</text>
            </g>
          );
        })}
        {characters.map(c => {
          const connected = isConnected(c.id);
          const radius = c.major?28:18;
          const color = avatarColors[c.id] || '#475569';
          const isH = hovered===c.id;
          return (
            <g key={c.id} style={{opacity: connected?1:0.2, transition:'opacity 200ms', cursor:'pointer'}} onMouseEnter={()=>setHovered(c.id)}>
              {isH && <circle cx={c.x} cy={c.y} r={radius+8} fill="none" stroke={color} strokeWidth={2} opacity={0.45}/>}
              <circle cx={c.x} cy={c.y} r={radius} fill={c.major?color:'#1e293b'} stroke={c.major?color:'#475569'} strokeWidth={c.major?2:1} opacity={c.ghost?0.7:1}/>
              {c.initial && <text x={c.x} y={c.y+6} fontSize={16} fill="#0d1117" textAnchor="middle" fontWeight={700}>{c.initial}</text>}
              <text x={c.x} y={c.y+radius+16} fontSize={c.major?13:11} fill="#e2e8f0" textAnchor="middle" fontWeight={c.major?600:400}>{c.name}</text>
              {c.role && c.major && <text x={c.x} y={c.y+radius+30} fontSize={10} fill="#94a3b8" textAnchor="middle">{c.role}</text>}
            </g>
          );
        })}
      </svg>

      <div className="px-4 py-2 text-[10px] text-neutral-500 border-t border-white/5 bg-black/20">
        인물에 마우스를 올리면 관계가 강조됩니다 · 드래그로 위치 이동
      </div>
    </div>
  );
}

// MapGenerator — 자동 지도
function MapGenerator({ accent = '#22d3ee' }) {
  const locs = [
    { id:'police',    name:'왕주 강력계',    x: 380, y: 270, type:'primary' },
    { id:'orphanage', name:'사랑들 보육원',  x: 170, y: 150, type:'secondary' },
    { id:'monspark',  name:'몬스파크 아파트',x: 560, y: 180, type:'secondary' },
    { id:'myhome',    name:'문영민의 집',    x: 260, y: 380, type:'secondary' },
    { id:'shinyoung', name:'신영그룹 본사',  x: 590, y: 400, type:'primary' },
  ];
  const routes = [
    { from:'police', to:'orphanage', label:'출퇴근', style:'dashed' },
    { from:'police', to:'monspark',  label:'수사', style:'dashed' },
    { from:'myhome', to:'police',    label:'동선' },
    { from:'shinyoung', to:'monspark', label:'자금 흐름', style:'dashed' },
  ];
  const lookup = (id) => locs.find(l => l.id===id);

  return (
    <div className="w-full h-full bg-[#0d1117] rounded-xl overflow-hidden border border-white/10 flex flex-col">
      <div className="px-4 py-2.5 flex items-center justify-between border-b border-white/5 bg-black/30 shrink-0">
        <div className="flex items-center gap-3">
          <span className="text-sm font-semibold text-neutral-200">배경 지도</span>
          <span className="text-[10px] text-neutral-500">자동 생성 · 장소 5곳</span>
        </div>
        <div className="flex items-center gap-2 text-[10px]">
          <span className="px-2 py-0.5 rounded border border-white/10 text-neutral-400">PNG</span>
          <span className="px-2 py-0.5 rounded font-medium text-black" style={{background: accent}}>지도 생성</span>
        </div>
      </div>
      <div className="flex-1 min-h-0">
        <svg viewBox="0 0 720 500" className="w-full h-full block" preserveAspectRatio="xMidYMid meet">
        <defs>
          <pattern id="mg-grid" width="32" height="32" patternUnits="userSpaceOnUse">
            <path d="M32 0H0V32" fill="none" stroke="rgba(255,255,255,0.035)"/>
          </pattern>
          <radialGradient id="mg-glow" cx="50%" cy="40%" r="70%">
            <stop offset="0%" stopColor="rgba(34,211,238,0.10)"/>
            <stop offset="100%" stopColor="rgba(0,0,0,0)"/>
          </radialGradient>
          <filter id="mg-blur"><feGaussianBlur stdDeviation="10"/></filter>
        </defs>
        <rect width="720" height="500" fill="url(#mg-grid)"/>
        <rect width="720" height="500" fill="url(#mg-glow)"/>
        {/* river/road abstract strokes */}
        <path d="M 0 320 Q 200 260, 360 300 T 720 260" fill="none" stroke="rgba(34,211,238,0.12)" strokeWidth="18" strokeLinecap="round"/>
        <path d="M 0 320 Q 200 260, 360 300 T 720 260" fill="none" stroke="rgba(34,211,238,0.35)" strokeWidth="1.5"/>
        <path d="M 120 40 L 180 460" stroke="rgba(255,255,255,0.06)" strokeWidth="20" strokeLinecap="round"/>
        <path d="M 600 40 L 560 470" stroke="rgba(255,255,255,0.06)" strokeWidth="20" strokeLinecap="round"/>
        {/* districts */}
        <rect x="40" y="80" width="220" height="140" rx="10" fill="rgba(255,255,255,0.02)" stroke="rgba(255,255,255,0.06)"/>
        <text x="54" y="100" fontSize="10" fill="rgba(255,255,255,0.35)">왕주구</text>
        <rect x="440" y="70" width="240" height="170" rx="10" fill="rgba(255,255,255,0.02)" stroke="rgba(255,255,255,0.06)"/>
        <text x="454" y="90" fontSize="10" fill="rgba(255,255,255,0.35)">신영동</text>
        <rect x="440" y="320" width="240" height="150" rx="10" fill="rgba(255,255,255,0.02)" stroke="rgba(255,255,255,0.06)"/>
        <text x="454" y="340" fontSize="10" fill="rgba(255,255,255,0.35)">경제구</text>

        {/* routes */}
        {routes.map((r,i) => {
          const f = lookup(r.from), t = lookup(r.to); if (!f||!t) return null;
          const mx = (f.x+t.x)/2, my = (f.y+t.y)/2;
          return (
            <g key={i}>
              <line x1={f.x} y1={f.y} x2={t.x} y2={t.y} stroke="rgba(34,211,238,0.55)" strokeWidth="1.5" strokeDasharray={r.style==='dashed'?'4 4':undefined}/>
              <text x={mx} y={my-6} fontSize="10" fill="#94a3b8" textAnchor="middle" style={{paintOrder:'stroke', stroke:'#0d1117', strokeWidth:3, strokeLinejoin:'round'}}>{r.label}</text>
            </g>
          );
        })}
        {/* pins */}
        {locs.map((l,i) => {
          const primary = l.type==='primary';
          return (
            <g key={l.id}>
              <circle cx={l.x} cy={l.y} r={primary?18:12} fill={primary?accent:'#1e293b'} stroke={primary?accent:'#475569'} strokeWidth={primary?2:1}/>
              {primary && <circle cx={l.x} cy={l.y} r="24" fill="none" stroke={accent} strokeWidth="1" opacity="0.35"/>}
              <text x={l.x} y={l.y + (primary?5:4)} fontSize={primary?12:10} fill={primary?'#0d1117':'#cbd5e1'} textAnchor="middle" fontWeight={700}>{i+1}</text>
              <text x={l.x} y={l.y + (primary?38:28)} fontSize={11} fill="#e2e8f0" textAnchor="middle" fontWeight={primary?600:400} style={{paintOrder:'stroke', stroke:'#0d1117', strokeWidth:3, strokeLinejoin:'round'}}>{l.name}</text>
            </g>
          );
        })}
      </svg>
      </div>
      <div className="px-4 py-2 text-[10px] text-neutral-500 border-t border-white/5 bg-black/20 flex items-center justify-between shrink-0">
        <span>장소 드래그 · 경로 자동 계산</span>
        <span>축척 자동</span>
      </div>
    </div>
  );
}

// Timeline — 일반 연표 + 설정 어긋남 플래그
function TimelineMockup({ accent = '#22d3ee' }) {
  // Horizontal timeline like a standard annotated chronology.
  // Each event is a dot on the axis with title above/below.
  // Flags appear when something contradicts settings.
  const events = [
    { ch: 1,  title:'아버지 사망',     side:'top',    kind:'beat' },
    { ch: 3,  title:'USB 복선',        side:'bottom', kind:'seed',  note:'강건 주머니' },
    { ch: 5,  title:'차수연 등장',     side:'top',    kind:'char' },
    { ch: 7,  title:'능력 각성',       side:'top',    kind:'beat' },
    { ch: 9,  title:'부친의 일기',     side:'bottom', kind:'seed' },
    { ch: 11, title:'주화진 등장',     side:'top',    kind:'char' },
    { ch: 13, title:'신영그룹 대치',   side:'top',    kind:'beat',
              flag:{ type:'warn', msg:'3화에서 강건 나이 24세로 설정됨. 현 시점 서술은 22세.' }},
    { ch: 16, title:'USB 회수',        side:'bottom', kind:'payoff', link: 3 },
    { ch: 18, title:'차수연 정체',     side:'top',    kind:'twist',
              flag:{ type:'hint', msg:'5화 등장 당시 "경찰대 출신" 소개. 현재 "신영 내부자"와 충돌 가능.' }},
    { ch: 20, title:'1부 완결',        side:'top',    kind:'beat' },
  ];
  const chapters = 24;
  const leftPad = 40;
  const rightPad = 40;
  const vbW = 1040;
  const vbH = 500;
  const axisY = vbH / 2;
  const xOf = (ch) => leftPad + (vbW - leftPad - rightPad) * ((ch - 1) / (chapters - 1));
  const kindColor = {
    beat:   '#22d3ee',
    seed:   '#f59e0b',
    payoff: '#f59e0b',
    char:   '#c084fc',
    twist:  '#fb7185',
  };
  const kindLabel = {
    beat:'주요 사건', seed:'복선', payoff:'회수', char:'캐릭터', twist:'반전',
  };

  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-white/10 h-full flex flex-col">
      <div className="px-4 py-2.5 flex items-center justify-between border-b border-white/5 bg-black/30 shrink-0">
        <div className="flex items-center gap-3">
          <span className="text-sm font-semibold text-neutral-200">타임라인</span>
          <span className="text-[10px] text-neutral-500">1부 · 24화 · 사건 10건</span>
        </div>
        <div className="flex items-center gap-2 text-[10px]">
          <span className="px-2 py-0.5 rounded border border-rose-500/30 bg-rose-500/10 text-rose-300 flex items-center gap-1">
            <span className="w-1.5 h-1.5 rounded-full bg-rose-400"/>설정 충돌 2건
          </span>
          <span className="px-2 py-0.5 rounded border border-white/10 text-neutral-400">PNG</span>
        </div>
      </div>
      <div className="scroll-x overflow-x-auto flex-1">
        <svg viewBox={`0 0 ${vbW} ${vbH}`} className="block w-full h-full" style={{minWidth:'100%'}} preserveAspectRatio="xMidYMid meet">
          <defs>
            <pattern id="tl-grid" width="40" height="40" patternUnits="userSpaceOnUse">
              <path d="M40 0H0V40" fill="none" stroke="rgba(255,255,255,0.03)"/>
            </pattern>
            <filter id="tl-flag-glow">
              <feGaussianBlur stdDeviation="4"/>
            </filter>
          </defs>
          <rect width={vbW} height={vbH} fill="url(#tl-grid)"/>

          {/* main axis */}
          <line x1={leftPad} y1={axisY} x2={vbW - rightPad} y2={axisY} stroke="rgba(255,255,255,0.25)" strokeWidth="1.2"/>
          {/* chapter ticks */}
          {Array.from({length: chapters}, (_,i) => {
            const x = xOf(i+1);
            const major = (i+1)%5===0 || i===0 || i===chapters-1;
            return (
              <g key={i}>
                <line x1={x} y1={axisY - (major?6:3)} x2={x} y2={axisY + (major?6:3)} stroke="rgba(255,255,255,0.28)" strokeWidth={major?1.2:0.8}/>
                {major && <text x={x} y={axisY + 22} fontSize={11} fill="#64748b" textAnchor="middle" fontFamily="ui-monospace, monospace">{i+1}화</text>}
              </g>
            );
          })}

          {/* foreshadow → payoff connector */}
          {events.filter(e => e.kind==='payoff' && e.link).map((p,i) => {
            const seed = events.find(s => s.ch===p.link && s.kind==='seed');
            if (!seed) return null;
            const x1 = xOf(seed.ch), x2 = xOf(p.ch);
            const midY = axisY + 120;
            return (
              <path key={i} d={`M ${x1} ${axisY+4} Q ${(x1+x2)/2} ${midY}, ${x2} ${axisY+4}`}
                fill="none" stroke={kindColor.seed} strokeWidth="1.2" strokeDasharray="3 4" opacity="0.55"/>
            );
          })}

          {/* events */}
          {events.map((e,i) => {
            const x = xOf(e.ch);
            const up = e.side==='top';
            const stemStart = axisY;
            const stemEnd = up ? axisY - 50 : axisY + 50;
            const labelY = up ? stemEnd - 8 : stemEnd + 16;
            const boxY = up ? stemEnd - 44 : stemEnd + 4;
            const color = kindColor[e.kind];
            return (
              <g key={i}>
                {/* stem */}
                <line x1={x} y1={stemStart} x2={x} y2={stemEnd} stroke={color} strokeWidth="1.4" opacity="0.7"/>
                {/* dot */}
                <circle cx={x} cy={axisY} r="5" fill="#0d1117" stroke={color} strokeWidth="2"/>
                <circle cx={x} cy={axisY} r="2" fill={color}/>
                {/* label box */}
                <rect x={x-62} y={boxY} width="124" height="40" rx="6" fill="rgba(255,255,255,0.03)" stroke={`${color}55`}/>
                <text x={x} y={boxY+15} fontSize={9.5} fill={color} textAnchor="middle" fontWeight={600} letterSpacing="0.5">{e.ch}화 · {kindLabel[e.kind]}</text>
                <text x={x} y={boxY+31} fontSize={12} fill="#e2e8f0" textAnchor="middle" fontWeight={500}>{e.title}</text>
                {/* flag */}
                {e.flag && (() => {
                  const flagColor = e.flag.type==='warn' ? '#fb7185' : '#fbbf24';
                  const flagY = up ? boxY - 16 : boxY + 48;
                  return (
                    <g>
                      <line x1={x+50} y1={up?boxY:boxY+40} x2={x+50} y2={flagY + (up?8:-4)} stroke={flagColor} strokeWidth="1" opacity="0.6"/>
                      <circle cx={x+50} cy={flagY} r="9" fill={`${flagColor}22`} stroke={flagColor} strokeWidth="1.2" filter="url(#tl-flag-glow)" opacity="0.5"/>
                      <circle cx={x+50} cy={flagY} r="9" fill={`${flagColor}22`} stroke={flagColor} strokeWidth="1.2"/>
                      <path d={`M ${x+47} ${flagY-4} L ${x+47} ${flagY+4} M ${x+47} ${flagY-4} L ${x+54} ${flagY-1} L ${x+47} ${flagY+2}`} stroke={flagColor} strokeWidth="1.3" fill={flagColor} fillOpacity="0.4" strokeLinejoin="round"/>
                    </g>
                  );
                })()}
              </g>
            );
          })}

          {/* flag detail callout (for 13화) */}
          {(() => {
            const flagged = events.find(e => e.ch===13);
            if (!flagged?.flag) return null;
            const x = xOf(flagged.ch);
            return (
              <g transform={`translate(${x+70}, ${axisY - 150})`}>
                <rect x="0" y="0" width="230" height="68" rx="8" fill="rgba(251,113,133,0.08)" stroke="rgba(251,113,133,0.5)"/>
                <g transform="translate(12, 14)">
                  <circle cx="5" cy="5" r="6" fill="rgba(251,113,133,0.2)" stroke="#fb7185" strokeWidth="1"/>
                  <path d="M2 1 L2 9 M2 1 L9 4 L2 7" stroke="#fb7185" strokeWidth="1.2" fill="rgba(251,113,133,0.6)"/>
                </g>
                <text x="30" y="21" fontSize="10" fill="#fb7185" fontWeight={700} letterSpacing="0.5">설정 충돌</text>
                <foreignObject x="12" y="28" width="210" height="38">
                  <div xmlns="http://www.w3.org/1999/xhtml" style={{fontSize:10.5, color:'#fecdd3', lineHeight:1.4}}>
                    3화에서 강건 나이 <b style={{color:'#fff'}}>24세</b>로 설정. 현 시점 서술은 <b style={{color:'#fff'}}>22세</b>.
                  </div>
                </foreignObject>
              </g>
            );
          })()}
        </svg>
      </div>
      <div className="px-4 py-2.5 border-t border-white/5 bg-black/20 flex items-center gap-4 text-[10px] text-neutral-500 shrink-0 flex-wrap">
        {Object.entries(kindLabel).map(([k, l]) => (
          <span key={k} className="flex items-center gap-1.5">
            <span className="w-2 h-2 rounded-full" style={{background: kindColor[k]}}/>{l}
          </span>
        ))}
        <span className="flex items-center gap-1.5">
          <span className="w-2 h-2 rounded-full bg-rose-400"/>설정 충돌 플래그
        </span>
      </div>
    </div>
  );
}

// StreakCalendar — 출석 도장
function StreakCalendar({ accent = '#22d3ee' }) {
  // 5 weeks x 7 days. Data: idx → state
  const today = 18;
  const states = [
    // 0: empty, 1: stamp, 2: sp, 3: bonus (fire), 4: today
    1,1,0,1,1,0,0,
    1,1,1,1,1,1,1, // week bonus row
    2,1,1,1,1,0,1,
    0,1,1,4,0,0,0,
    0,0,0,0,0,0,0,
  ];
  const labels = ['일','월','화','수','목','금','토'];
  const streak = 7;
  const totalDays = 21;

  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-orange-500/20">
      <div className="px-5 py-4 flex items-center justify-between border-b border-white/5 bg-gradient-to-r from-orange-500/10 to-transparent">
        <div>
          <div className="text-xs text-orange-300 font-semibold tracking-wider uppercase mb-0.5">매일 쓰면 보상!</div>
          <div className="text-lg font-bold text-white">11월 출석 도장</div>
        </div>
        <div className="text-right">
          <div className="flex items-center gap-1.5 justify-end text-orange-400">
            <I.Flame size={16}/>
            <span className="text-2xl font-bold tabular-nums">{streak}</span>
            <span className="text-xs text-neutral-400">일 연속</span>
          </div>
          <div className="text-[10px] text-neutral-500 mt-0.5">누적 {totalDays}일</div>
        </div>
      </div>
      <div className="p-5">
        <div className="grid grid-cols-7 gap-1.5 mb-2">
          {labels.map((l,i) => (
            <div key={i} className={`text-center text-[10px] font-medium ${i===0?'text-red-400/70':i===6?'text-blue-400/70':'text-neutral-500'}`}>{l}</div>
          ))}
        </div>
        <div className="grid grid-cols-7 gap-1.5">
          {states.map((s,i) => {
            const base = "aspect-square rounded-md flex items-center justify-center relative text-[10px]";
            if (s===0) return <div key={i} className={`${base} bg-white/[0.02] border border-white/5 text-neutral-700`}>{i+1}</div>;
            if (s===1) return (
              <div key={i} className={`${base} bg-orange-500/10 border border-orange-500/30`}>
                <I.Check size={14} className="text-orange-400"/>
              </div>
            );
            if (s===2) return (
              <div key={i} className={`${base} bg-cyan-500/10 border border-cyan-500/30 text-cyan-300 font-bold`}>
                +5
              </div>
            );
            if (s===3) return (
              <div key={i} className={`${base} bg-orange-500/20 border border-orange-500/50 text-orange-300`}>
                <I.Flame size={14}/>
              </div>
            );
            if (s===4) return (
              <div key={i} className={`${base} bg-white border-2 border-white text-black font-bold`}>
                {i-6}
              </div>
            );
            return null;
          })}
        </div>
        {/* streak row highlight */}
        <div className="mt-4 p-3 rounded-lg bg-orange-500/10 border border-orange-500/30 flex items-center gap-3">
          <I.Flame size={18} className="text-orange-400"/>
          <div className="flex-1">
            <div className="text-sm text-white font-semibold">7일 연속 달성!</div>
            <div className="text-[11px] text-neutral-400">보너스 SP 20 · 다음 목표 30일</div>
          </div>
          <div className="text-xs text-orange-300 font-bold">+20 SP</div>
        </div>
      </div>
    </div>
  );
}

// AssistantChat — 대화 UI with typing animation
const chatScripts = {
  consistency: {
    label: '캐릭터 일관성 검토',
    messages: [
      { from:'user', text:'강건이 최근 대화에서 너무 감정적인 거 같은데?' },
      { from:'ai', typing: 1200, text:'12화에서 강건이 차수연에게 "나도 가끔 무섭다"라고 했네요.\n1화 설정의 「감정을 드러내지 않는 형사」와 어긋나 보입니다.\n의도하신 변화인가요, 일관성을 유지할까요?' },
    ]
  },
  foreshadow: {
    label: '복선 추적',
    messages: [
      { from:'user', text:'3화에서 깔았던 복선 뭐였지?' },
      { from:'ai', typing: 1400, text:'3화 마지막 장면에서 강태식의 USB가 등장했고,\n"접근이 위험한 증거"로 명시되셨어요.\n현재 16화까지 회수 안 됐습니다. 타임라인에 표시해둘까요?' },
    ]
  },
  image: {
    label: '이미지 생성',
    messages: [
      { from:'user', text:'차수연 외형 이미지 하나 뽑아줘' },
      { from:'ai', typing: 1600, text:'등록된 설정 기반으로 생성합니다.\n「28세, 기자, 단발, 회색 트렌치코트」' },
      { from:'ai', typing: 2200, image: true },
    ]
  }
};

function TypingDots({ purple }) {
  return (
    <div className="inline-flex items-end gap-1 py-2 px-3 rounded-2xl" style={{background:'rgba(192,132,252,0.12)'}}>
      {[0,1,2].map(i => <span key={i} className="typing-dot inline-block w-1.5 h-1.5 rounded-full" style={{background:'#c084fc'}}/>)}
    </div>
  );
}

function AssistantChat() {
  const [scriptKey, setScriptKey] = React.useState('consistency');
  const [rendered, setRendered] = React.useState([]);
  const [typing, setTyping] = React.useState(false);
  const [runId, setRunId] = React.useState(0);

  React.useEffect(() => {
    let cancelled = false;
    const script = chatScripts[scriptKey];
    setRendered([]);
    setTyping(false);
    (async () => {
      for (let i = 0; i < script.messages.length; i++) {
        const m = script.messages[i];
        if (m.from === 'ai' && m.typing) {
          if (cancelled) return;
          setTyping(true);
          await new Promise(r => setTimeout(r, m.typing));
          if (cancelled) return;
          setTyping(false);
        } else {
          await new Promise(r => setTimeout(r, 400));
        }
        if (cancelled) return;
        setRendered(prev => [...prev, m]);
      }
    })();
    return () => { cancelled = true; };
  }, [scriptKey, runId]);

  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-purple-500/20">
      <div className="px-4 py-2.5 flex items-center justify-between border-b border-white/5 bg-black/30">
        <div className="flex items-center gap-2">
          <div className="w-6 h-6 rounded-md flex items-center justify-center" style={{background:'rgba(192,132,252,0.18)'}}>
            <I.Sparkles size={14} className="text-purple-300"/>
          </div>
          <span className="text-sm font-semibold text-neutral-200">어시스턴트</span>
          <span className="text-[10px] text-neutral-500">작품 전체 컨텍스트 로드됨 · 14,283 줄</span>
        </div>
        <div className="flex items-center gap-1 text-[10px]">
          {Object.entries(chatScripts).map(([k,v]) => (
            <button key={k} onClick={() => { setScriptKey(k); setRunId(r=>r+1); }}
              className={`px-2 py-0.5 rounded transition ${scriptKey===k?'bg-purple-500/20 text-purple-200 border border-purple-500/40':'text-neutral-400 border border-white/10 hover:border-white/20'}`}>
              {v.label}
            </button>
          ))}
        </div>
      </div>
      <div className="px-5 py-6 space-y-3 min-h-[320px] max-h-[400px] overflow-y-auto" style={{scrollbarWidth:'thin'}}>
        {rendered.map((m,i) => (
          <div key={i} className={`flex ${m.from==='user'?'justify-end':'justify-start'} bubble-in`}>
            <div className={`max-w-[80%] rounded-2xl px-4 py-2.5 text-sm leading-relaxed whitespace-pre-line ${
              m.from==='user' ? 'text-black font-medium' : 'text-neutral-200'}`}
              style={{
                background: m.from==='user' ? '#22d3ee' : 'rgba(192,132,252,0.12)',
                border: m.from==='ai' ? '1px solid rgba(192,132,252,0.25)' : 'none',
                borderBottomRightRadius: m.from==='user'?6:undefined,
                borderBottomLeftRadius: m.from==='ai'?6:undefined,
              }}>
              {m.image ? (
                <div className="flex items-center gap-3">
                  <div className="w-24 h-32 rounded-md bg-gradient-to-br from-purple-500/30 via-neutral-800 to-cyan-500/20 flex items-center justify-center border border-white/10">
                    <I.Image size={20} className="text-purple-200"/>
                  </div>
                  <div>
                    <div className="text-xs text-purple-200 font-semibold mb-1">차수연 초상 v1</div>
                    <div className="text-[11px] text-neutral-400 leading-relaxed">단발 · 회색 트렌치코트 · 기자 배지</div>
                    <div className="mt-2 flex gap-1">
                      <span className="text-[10px] px-1.5 py-0.5 rounded border border-white/10 text-neutral-300">다른 버전</span>
                      <span className="text-[10px] px-1.5 py-0.5 rounded bg-purple-500/30 text-purple-100">설정에 저장</span>
                    </div>
                  </div>
                </div>
              ) : m.text}
            </div>
          </div>
        ))}
        {typing && (
          <div className="flex justify-start bubble-in">
            <TypingDots/>
          </div>
        )}
      </div>
      <div className="px-4 py-3 border-t border-white/5 flex items-center gap-2">
        <div className="flex-1 px-3 py-2 rounded-lg bg-white/[0.03] border border-white/10 text-sm text-neutral-500">
          캐릭터, 복선, 설정 — 무엇이든 물어보세요
        </div>
        <button className="w-9 h-9 rounded-lg flex items-center justify-center" style={{background:'rgba(192,132,252,0.2)', color:'#c084fc'}}>
          <I.Send size={16}/>
        </button>
      </div>
    </div>
  );
}

// ManuscriptEditor — 원고 대시보드
function ManuscriptEditor({ accent = '#22d3ee' }) {
  const scenes = [
    { idx:'12-1', color:'#22d3ee', title:'강건, 경찰서 복도', tag:'강건' },
    { idx:'12-2', color:'#f87171', title:'이창현 자택',       tag:'이창현' },
    { idx:'12-3', color:'#34d399', title:'차수연 카페 접선',   tag:'차수연', active:true },
    { idx:'12-4', color:'#c084fc', title:'주화진 사무실',     tag:'주화진' },
    { idx:'12-5', color:'#f59e0b', title:'플래시백: 부친 유언', tag:'복선' },
  ];

  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-white/10">
      <div className="px-4 py-2 flex items-center justify-between border-b border-white/5 bg-black/30">
        <div className="flex items-center gap-3">
          <div className="flex gap-1.5">
            <span className="w-2.5 h-2.5 rounded-full bg-red-400/70"/>
            <span className="w-2.5 h-2.5 rounded-full bg-yellow-400/70"/>
            <span className="w-2.5 h-2.5 rounded-full bg-green-400/70"/>
          </div>
          <span className="text-xs text-neutral-400">왕주의 형사 — 12화.md</span>
        </div>
        <div className="flex items-center gap-3 text-[10px] text-neutral-400">
          <span><span className="text-white font-bold">2,847</span> / 5,500자</span>
          <span className="px-2 py-0.5 rounded bg-white/5">저장됨</span>
        </div>
      </div>

      <div className="grid grid-cols-[180px_1fr] min-h-[360px]">
        {/* Scene sidebar with index tape */}
        <div className="border-r border-white/5 bg-black/20 p-2 space-y-1">
          <div className="text-[10px] text-neutral-500 px-2 py-1 uppercase tracking-wider">12화 장면</div>
          {scenes.map((s,i) => (
            <div key={i} className={`group relative flex items-center gap-2 pl-3 pr-2 py-2 rounded-md cursor-pointer ${s.active?'bg-white/[0.06]':'hover:bg-white/[0.03]'}`}>
              <span className="absolute left-0 top-1 bottom-1 w-1 rounded-r" style={{background: s.color}}/>
              <div className="flex-1 min-w-0">
                <div className="text-[10px] text-neutral-500 font-mono">{s.idx}</div>
                <div className={`text-xs truncate ${s.active?'text-white font-medium':'text-neutral-300'}`}>{s.title}</div>
                <div className="text-[9px] mt-0.5" style={{color: s.color}}>@{s.tag}</div>
              </div>
            </div>
          ))}
          <div className="text-[10px] text-neutral-500 px-2 py-1 mt-3 border-t border-white/5 pt-3">
            <div className="flex items-center justify-between mb-1"><span>캐릭터</span><span>5</span></div>
            <div className="flex items-center justify-between mb-1"><span>배경</span><span>3</span></div>
            <div className="flex items-center justify-between"><span>복선</span><span>2</span></div>
          </div>
        </div>

        {/* Editor */}
        <div className="p-6 relative">
          <div className="text-[11px] font-mono mb-3" style={{color: '#34d399'}}>12-3 · 차수연 카페 접선</div>
          <div className="max-w-[520px] space-y-3 text-[13px] leading-[1.85] text-neutral-200">
            <p>
              창가 자리였다. <span className="underline decoration-dotted decoration-[#34d399] underline-offset-2">차수연</span>은 이미 와서 커피를 절반쯤 비워둔 채였고, 
              <span className="underline decoration-dotted decoration-[#22d3ee] underline-offset-2"> 강건</span>은 맞은편에 앉으며 외투를 벗지 않았다.
            </p>
            <p>
              "늦었네요."
            </p>
            <p>
              "오는 길에 추적당한 것 같아서." 강건이 주머니에서 <span className="bg-orange-500/15 border-b border-orange-500/40">USB</span>를 꺼냈다. "이거, 지난번 카페에서 말씀드렸던 그겁니다."
            </p>
            <p>
              차수연의 얼굴이 굳었다. "설마…"<span className="blinker" style={{color: accent}}>▌</span>
            </p>
          </div>

          {/* floating sprint timer */}
          <div className="absolute right-5 bottom-5 flex items-center gap-2 px-3 py-2 rounded-lg bg-black/60 border border-white/10 backdrop-blur-sm">
            <I.Clock size={14} className="text-cyan-400"/>
            <span className="text-xs font-mono text-white tabular-nums">14:21</span>
            <span className="text-[10px] text-neutral-500">스프린트</span>
            <span className="text-[10px] text-cyan-300 font-semibold">+412자</span>
          </div>

          {/* floating connections hint */}
          <div className="absolute left-5 bottom-5 text-[10px] text-neutral-500 flex items-center gap-2">
            <I.Sparkles size={12} className="text-purple-300"/>
            자동 연결: 차수연 · 강건 · USB(복선)
          </div>
        </div>
      </div>
    </div>
  );
}

// Planner mode toggle mockup (Plotter vs Pantser)
function ModeToggleMockup() {
  const [mode, setMode] = React.useState('plotter');
  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-white/10">
      <div className="px-4 py-2.5 flex items-center justify-between border-b border-white/5 bg-black/30">
        <span className="text-sm font-semibold text-neutral-200">12화 작성</span>
        <div className="flex items-center gap-0.5 p-0.5 rounded-md bg-black/40 border border-white/10">
          {[{k:'plotter',l:'플로터'},{k:'pantser',l:'팬서'}].map(o => (
            <button key={o.k} onClick={()=>setMode(o.k)}
              className={`px-3 py-1 text-[11px] rounded transition ${mode===o.k?'bg-cyan-500 text-black font-semibold':'text-neutral-400'}`}>
              {o.l}
            </button>
          ))}
        </div>
      </div>
      <div className="p-5 min-h-[280px]">
        {mode==='plotter' ? (
          <div className="space-y-2.5">
            <div className="text-[10px] text-neutral-500 uppercase tracking-wider mb-3">구조 먼저</div>
            {[
              {n:'도입', d:'차수연에게 접선 요청', s:'✓', c:'#22d3ee'},
              {n:'전개', d:'USB 공개 · 위험 경고', s:'✓', c:'#22d3ee'},
              {n:'전환', d:'추적자 발각', s:'...', c:'#94a3b8'},
              {n:'절정', d:'추격전', s:'', c:'#475569'},
              {n:'결말', d:'은신처 이동 → 13화 훅', s:'', c:'#475569'},
            ].map((s,i) => (
              <div key={i} className="flex items-center gap-3 p-3 rounded-lg bg-white/[0.02] border border-white/5">
                <span className="w-6 h-6 rounded-full border flex items-center justify-center text-[10px] font-bold" style={{borderColor: s.c, color: s.c}}>{i+1}</span>
                <div className="flex-1">
                  <div className="text-xs text-white font-semibold">{s.n}</div>
                  <div className="text-[11px] text-neutral-400">{s.d}</div>
                </div>
                <span className="text-xs" style={{color: s.c}}>{s.s}</span>
              </div>
            ))}
          </div>
        ) : (
          <div className="space-y-2">
            <div className="text-[10px] text-neutral-500 uppercase tracking-wider mb-3">쓰면서 정리</div>
            <div className="text-[13px] leading-[1.8] text-neutral-200 max-w-[480px]">
              <p>창가 자리였다. 차수연은 이미 와서 커피를 절반쯤 비워둔 채였다. 강건은 맞은편에 앉으며 외투를 벗지 않았다.</p>
              <p className="mt-2">"늦었네요."</p>
              <p className="mt-2 text-neutral-500">"오는 길에 추적당한 것 같아서."<span className="blinker text-cyan-400">▌</span></p>
            </div>
            <div className="mt-5 flex items-start gap-2 p-3 rounded-lg bg-purple-500/5 border border-purple-500/20">
              <I.Sparkles size={14} className="text-purple-300 mt-0.5"/>
              <div className="flex-1">
                <div className="text-[10px] text-purple-300 font-semibold uppercase tracking-wider">어시스턴트 자동 정리</div>
                <div className="text-[11px] text-neutral-300 mt-1">장면: 차수연 카페 접선 · 등장: 강건, 차수연 · 소품: USB(3화 복선)</div>
              </div>
              <span className="text-[10px] px-2 py-1 rounded bg-purple-500/20 text-purple-200">구조 추출</span>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// Character dashboard mockup
function CharacterDashMockup() {
  const chars = [
    { name:'강건', role:'주인공', color:'#22d3ee', tags:['28세','형사','무뚝뚝'], scenes: 42 },
    { name:'차수연', role:'협력자', color:'#34d399', tags:['기자','28세','단발'], scenes: 18 },
    { name:'이창현', role:'적대', color:'#f87171', tags:['정치가','45세','야심'], scenes: 23 },
    { name:'주화진', role:'후원자', color:'#c084fc', tags:['재단 이사','50세'], scenes: 9 },
  ];
  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-white/10">
      <div className="px-4 py-2.5 flex items-center justify-between border-b border-white/5 bg-black/30">
        <div className="flex items-center gap-3">
          <span className="text-sm font-semibold text-neutral-200">캐릭터</span>
          <span className="text-[10px] text-neutral-500">12명 등록 · 5명 주요</span>
        </div>
        <span className="text-[10px] text-neutral-400 px-2 py-0.5 rounded border border-white/10">+ 새 캐릭터</span>
      </div>
      <div className="p-4 grid grid-cols-2 gap-3">
        {chars.map((c,i) => (
          <div key={i} className="p-3 rounded-lg bg-white/[0.02] border border-white/5 hover:border-white/15 transition">
            <div className="flex items-start gap-3">
              <div className="w-10 h-10 rounded-full flex items-center justify-center text-black font-bold text-sm" style={{background: c.color}}>
                {c.name[0]}
              </div>
              <div className="flex-1 min-w-0">
                <div className="flex items-baseline gap-2">
                  <span className="text-sm text-white font-semibold">{c.name}</span>
                  <span className="text-[10px]" style={{color: c.color}}>{c.role}</span>
                </div>
                <div className="flex flex-wrap gap-1 mt-1.5">
                  {c.tags.map((t,j)=> <span key={j} className="text-[9px] px-1.5 py-0.5 rounded bg-white/5 text-neutral-400">{t}</span>)}
                </div>
                <div className="text-[10px] text-neutral-500 mt-1.5">등장 장면 {c.scenes}개</div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// Hero app screenshot composite — 에디터 + 사이드바 + 어시스턴트
function HeroAppComposite({ accent = '#22d3ee' }) {
  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-white/10 shadow-2xl" style={{boxShadow: `0 40px 80px -20px rgba(34,211,238,0.15), 0 0 0 1px rgba(255,255,255,0.05)`}}>
      {/* title bar */}
      <div className="px-4 py-2.5 flex items-center gap-3 border-b border-white/5 bg-black/40">
        <div className="flex gap-1.5">
          <span className="w-3 h-3 rounded-full bg-red-400/70"/>
          <span className="w-3 h-3 rounded-full bg-yellow-400/70"/>
          <span className="w-3 h-3 rounded-full bg-green-400/70"/>
        </div>
        <div className="flex-1 text-center text-xs text-neutral-400">상태창 — 왕주의 형사</div>
        <div className="text-[10px] text-neutral-500">저장됨 · 방금 전</div>
      </div>
      <div className="grid grid-cols-[200px_1fr_280px] h-[460px]">
        {/* sidebar */}
        <div className="border-r border-white/5 bg-black/30 p-3 space-y-1 text-xs">
          <div className="text-[10px] text-neutral-500 uppercase tracking-wider px-1 mb-2">원고</div>
          {['1화','2화','3화','...','11화','12화','13화'].map((c,i) => (
            <div key={i} className={`px-2 py-1.5 rounded flex items-center justify-between ${c==='12화'?'bg-white/[0.06] text-white':'text-neutral-400'}`}>
              <span>{c}</span>
              {c==='12화' && <span className="text-[10px]" style={{color: accent}}>●</span>}
            </div>
          ))}
          <div className="text-[10px] text-neutral-500 uppercase tracking-wider px-1 mt-4 mb-2">설정</div>
          {[
            {n:'캐릭터', k:12},
            {n:'배경', k:8},
            {n:'자료', k:23},
          ].map((s,i) => (
            <div key={i} className="px-2 py-1.5 rounded flex items-center justify-between text-neutral-400 hover:bg-white/[0.03]">
              <span>{s.n}</span>
              <span className="text-[10px] text-neutral-600">{s.k}</span>
            </div>
          ))}
          <div className="text-[10px] text-neutral-500 uppercase tracking-wider px-1 mt-4 mb-2">시각화</div>
          {['인물관계도','배경 지도','타임라인'].map((s,i) => (
            <div key={i} className="px-2 py-1.5 rounded flex items-center gap-2 text-neutral-400 hover:bg-white/[0.03]">
              <span className="w-1 h-1 rounded-full bg-neutral-600"/>
              <span>{s}</span>
            </div>
          ))}
        </div>
        {/* editor */}
        <div className="p-6 overflow-hidden">
          <div className="text-[11px] font-mono text-emerald-400 mb-3">12-3 · 차수연 카페 접선</div>
          <div className="max-w-[480px] space-y-2.5 text-[13px] leading-[1.9] text-neutral-200">
            <p>창가 자리였다. <span className="underline decoration-dotted decoration-emerald-400 underline-offset-2">차수연</span>은 이미 와서 커피를 절반쯤 비워둔 채였고, <span className="underline decoration-dotted decoration-cyan-400 underline-offset-2">강건</span>은 맞은편에 앉으며 외투를 벗지 않았다.</p>
            <p>"늦었네요."</p>
            <p>"오는 길에 추적당한 것 같아서." 강건이 주머니에서 <span className="bg-orange-500/15 border-b border-orange-500/40">USB</span>를 꺼냈다.</p>
            <p>"이거, 지난번 카페에서 말씀드렸던 그겁니다."</p>
            <p>차수연의 얼굴이 굳었다. "설마…"<span className="blinker" style={{color: accent}}>▌</span></p>
          </div>
          <div className="absolute"/>
        </div>
        {/* assistant */}
        <div className="border-l border-white/5 bg-black/20 flex flex-col">
          <div className="px-3 py-2 border-b border-white/5 flex items-center gap-2">
            <div className="w-5 h-5 rounded flex items-center justify-center" style={{background:'rgba(192,132,252,0.18)'}}>
              <I.Sparkles size={11} className="text-purple-300"/>
            </div>
            <span className="text-xs font-semibold text-neutral-200">어시스턴트</span>
            <span className="ml-auto text-[9px] text-neutral-500">컨텍스트 로드됨</span>
          </div>
          <div className="flex-1 p-3 space-y-2 overflow-hidden text-[11px]">
            <div className="rounded-lg px-3 py-2 bg-cyan-500/10 border border-cyan-500/20 text-neutral-200 ml-6">
              <div className="text-[9px] text-cyan-300 font-semibold uppercase tracking-wider mb-1">내 질문</div>
              방금 쓴 USB 장면, 앞에 깐 복선하고 어긋나는 부분 있어?
            </div>
            <div className="rounded-lg px-3 py-2 bg-white/[0.03] border border-white/5 text-neutral-300">
              <div className="text-[9px] text-purple-300 font-semibold uppercase tracking-wider mb-1">어시스턴트</div>
              3화에서 <span className="text-orange-300">USB는 강건의 가방 안쪽 주머니</span>에 있었어요.
              지금 장면은 외투 주머니에서 꺼내는데, 동선상 문제는 없지만 3화 묘사와 위치가 달라요.
              의도하신 거라면 괜찮습니다.
            </div>
            <div className="rounded-lg px-3 py-2 bg-cyan-500/10 border border-cyan-500/20 text-neutral-200 ml-6">
              <div className="text-[9px] text-cyan-300 font-semibold uppercase tracking-wider mb-1">내 질문</div>
              차수연 대사 "설마…" 다음에 뭐가 자연스러울까?
            </div>
          </div>
          <div className="p-2 border-t border-white/5">
            <div className="px-2.5 py-2 rounded bg-white/[0.03] border border-white/10 text-[10px] text-neutral-500">무엇이든 물어보세요…</div>
          </div>
        </div>
      </div>
      {/* footer bar */}
      <div className="px-4 py-1.5 border-t border-white/5 bg-black/40 flex items-center justify-between text-[10px] text-neutral-500">
        <div className="flex items-center gap-3">
          <span className="flex items-center gap-1"><I.Clock size={10} className="text-cyan-400"/> 스프린트 14:21</span>
          <span>+412자</span>
          <span>SP 2,840</span>
        </div>
        <div className="flex items-center gap-3">
          <span>12화 · 2,847 / 5,500자</span>
          <span style={{color: accent}}>●</span>
        </div>
      </div>
    </div>
  );
}

// Submission doc mockup
function SubmissionMockup() {
  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-white/10">
      <div className="px-4 py-2.5 flex items-center justify-between border-b border-white/5 bg-black/30">
        <span className="text-sm font-semibold text-neutral-200">투고 자료</span>
        <span className="text-[10px] px-2 py-0.5 rounded bg-cyan-500 text-black font-semibold">DOCX 내보내기</span>
      </div>
      <div className="p-5 grid grid-cols-[1fr_140px] gap-4">
        <div className="bg-white/[0.03] border border-white/5 rounded-lg p-4 space-y-2 min-h-[220px]">
          <div className="h-2 rounded bg-white/15 w-1/2"/>
          <div className="h-2 rounded bg-white/10 w-2/3"/>
          <div className="h-px bg-white/10 my-3"/>
          <div className="text-[10px] text-neutral-500 uppercase tracking-wider">시놉시스</div>
          <div className="h-1.5 rounded bg-white/10 w-full"/>
          <div className="h-1.5 rounded bg-white/10 w-11/12"/>
          <div className="h-1.5 rounded bg-white/10 w-10/12"/>
          <div className="h-1.5 rounded bg-white/10 w-full"/>
          <div className="text-[10px] text-neutral-500 uppercase tracking-wider pt-2">등장인물</div>
          <div className="h-1.5 rounded bg-white/10 w-1/2"/>
          <div className="h-1.5 rounded bg-white/10 w-2/3"/>
          <div className="h-1.5 rounded bg-white/10 w-5/12"/>
        </div>
        <div className="space-y-2 text-[10px]">
          <div className="text-neutral-500 uppercase tracking-wider">포함된 섹션</div>
          {['표지','기본정보','시놉시스','등장인물 5명','세계관','1~3화 본문'].map((s,i) => (
            <div key={i} className="flex items-center gap-2 text-neutral-300">
              <I.Check size={12} className="text-cyan-400"/>
              {s}
            </div>
          ))}
          <div className="pt-2 text-[10px] text-neutral-500">문피아 템플릿 v3</div>
        </div>
      </div>
    </div>
  );
}

// Analytics mockup
function AnalyticsMockup() {
  const data = [45, 62, 58, 71, 69, 82, 88, 95, 91, 87, 92, 98, 94, 102, 108, 115];
  const max = Math.max(...data);
  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-white/10">
      <div className="px-4 py-2.5 flex items-center justify-between border-b border-white/5 bg-black/30">
        <span className="text-sm font-semibold text-neutral-200">연재 실적</span>
        <div className="flex gap-1 text-[10px]">
          <span className="px-2 py-0.5 rounded bg-white/5 text-neutral-400">7일</span>
          <span className="px-2 py-0.5 rounded bg-cyan-500/20 text-cyan-300 border border-cyan-500/30">30일</span>
          <span className="px-2 py-0.5 rounded bg-white/5 text-neutral-400">전체</span>
        </div>
      </div>
      <div className="p-5">
        <div className="flex items-end gap-4 mb-5">
          <div>
            <div className="text-[10px] text-neutral-500 uppercase tracking-wider">연독률</div>
            <div className="text-3xl font-bold text-white tabular-nums">87.4<span className="text-lg text-neutral-400">%</span></div>
            <div className="text-[10px] text-emerald-400">+4.2% 전주 대비</div>
          </div>
          <div className="flex-1"/>
          <div>
            <div className="text-[10px] text-neutral-500 uppercase tracking-wider">유료화</div>
            <div className="text-lg font-bold text-white">15화 권장</div>
            <div className="text-[10px] text-neutral-400">데이터 기반</div>
          </div>
        </div>
        <svg viewBox="0 0 320 100" className="w-full h-24">
          <defs>
            <linearGradient id="chart-grad" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor="#22d3ee" stopOpacity="0.5"/>
              <stop offset="100%" stopColor="#22d3ee" stopOpacity="0"/>
            </linearGradient>
          </defs>
          <path d={`M 0 ${100 - (data[0]/max)*90} ${data.map((v,i) => `L ${(i/(data.length-1))*320} ${100 - (v/max)*90}`).join(' ')}`}
            fill="none" stroke="#22d3ee" strokeWidth="1.5"/>
          <path d={`M 0 ${100 - (data[0]/max)*90} ${data.map((v,i) => `L ${(i/(data.length-1))*320} ${100 - (v/max)*90}`).join(' ')} L 320 100 L 0 100 Z`}
            fill="url(#chart-grad)"/>
          {data.map((v,i) => (
            <circle key={i} cx={(i/(data.length-1))*320} cy={100 - (v/max)*90} r="2" fill="#0d1117" stroke="#22d3ee" strokeWidth="1.2"/>
          ))}
        </svg>
        <div className="mt-4 p-3 rounded-lg bg-white/[0.02] border border-white/5 text-[11px] text-neutral-300 flex items-start gap-2">
          <I.Sparkles size={12} className="text-purple-300 mt-0.5"/>
          <span><strong className="text-white">13화 이후 연독률 급등.</strong> 차수연 등장 시점과 정확히 일치 — 이 캐릭터 비중을 늘려보세요.</span>
        </div>
      </div>
    </div>
  );
}

// Together room mockup
function TogetherMockup({ accent = '#22d3ee' }) {
  const rooms = [
    { name:'새벽 5~7시 방', host:'휴모르', seats:'8/12', live:true, writing: 7 },
    { name:'출근 전 원고', host:'달빛작가', seats:'5/10', writing: 5 },
    { name:'점심 스프린트', host:'별헤는이', seats:'2/8', writing: 2 },
    { name:'깊은 밤', host:'묵필', seats:'11/12', live:true, writing: 11 },
  ];
  return (
    <div className="w-full bg-[#0d1117] rounded-xl overflow-hidden border border-cyan-500/20">
      <div className="px-5 py-4 flex items-center justify-between border-b border-white/5 bg-gradient-to-r from-cyan-500/10 to-transparent">
        <div>
          <div className="text-xs text-cyan-300 font-semibold tracking-wider uppercase mb-0.5">함께쓰기</div>
          <div className="text-lg font-bold text-white">열려 있는 방</div>
        </div>
        <div className="text-right text-[11px] text-neutral-400">지금 <span className="text-cyan-300 font-bold">43명</span>이 집필 중</div>
      </div>
      <div className="p-3 space-y-2">
        {rooms.map((r,i) => (
          <div key={i} className="flex items-center gap-3 px-3 py-3 rounded-lg bg-white/[0.02] border border-white/5 hover:border-white/15 transition">
            <div className="flex -space-x-2">
              {Array.from({length: Math.min(r.writing, 4)}).map((_,j) => (
                <span key={j} className="w-7 h-7 rounded-full border-2 border-[#0d1117]" style={{background: ['#22d3ee','#c084fc','#34d399','#f59e0b'][j%4]}}/>
              ))}
              {r.writing > 4 && <span className="w-7 h-7 rounded-full border-2 border-[#0d1117] bg-neutral-800 flex items-center justify-center text-[9px] text-neutral-400">+{r.writing-4}</span>}
            </div>
            <div className="flex-1 min-w-0">
              <div className="flex items-center gap-2">
                <span className="text-sm text-white font-medium truncate">{r.name}</span>
                {r.live && <span className="flex items-center gap-1 text-[10px] text-cyan-300"><span className="w-1.5 h-1.5 rounded-full bg-cyan-400 animate-pulse"/>LIVE</span>}
              </div>
              <div className="text-[10px] text-neutral-500">방장 {r.host} · {r.seats}</div>
            </div>
            <button className="text-[11px] px-3 py-1.5 rounded font-semibold" style={{background: 'rgba(34,211,238,0.15)', color: accent, border: `1px solid ${accent}40`}}>
              입장
            </button>
          </div>
        ))}
      </div>
    </div>
  );
}

Object.assign(window, {
  CharacterMap, MapGenerator, TimelineMockup, StreakCalendar,
  AssistantChat, ManuscriptEditor, ModeToggleMockup, CharacterDashMockup,
  HeroAppComposite, SubmissionMockup, AnalyticsMockup, TogetherMockup,
});
