// Album jacket "artwork" — SVG placeholders, each genre has its own visual vocabulary.
// All placeholders are intentionally typographic/geometric so the user can swap in
// real illustration later. No hand-drawn figurative illustration here.

const { useMemo } = React;

// ------------------------------------------------------------
// Striped placeholder used as "illustration to be dropped in"
// ------------------------------------------------------------
function StripedPlaceholder({ label = 'ILLUSTRATION', tint = '#1a1410', accent = '#d8c9a3', note }) {
  const id = 'sp-' + Math.random().toString(36).slice(2, 7);
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <defs>
        <pattern id={id} width="10" height="10" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
          <rect width="10" height="10" fill={tint}/>
          <line x1="0" y1="0" x2="0" y2="10" stroke={accent} strokeOpacity="0.12" strokeWidth="1"/>
        </pattern>
      </defs>
      <rect width="400" height="400" fill={`url(#${id})`}/>
      <rect x="1" y="1" width="398" height="398" fill="none" stroke={accent} strokeOpacity="0.2"/>
      <text x="200" y="200" textAnchor="middle" fontFamily="JetBrains Mono, monospace"
            fontSize="11" letterSpacing="3" fill={accent} opacity="0.55">{label}</text>
      {note && <text x="200" y="220" textAnchor="middle" fontFamily="JetBrains Mono, monospace"
            fontSize="9" letterSpacing="2" fill={accent} opacity="0.35">{note}</text>}
    </svg>
  );
}

// ============================================================
// Album jacket variants — each is typographic, brand-forward
// ============================================================

// 1) Ink seal — Wuxia ink-wash vibe, big serif title + seal
function Jacket_InkSeal({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <rect width="400" height="400" fill="#0f0b08"/>
      {/* subtle ink wash */}
      <defs>
        <radialGradient id="ink1" cx="30%" cy="40%">
          <stop offset="0%" stopColor="#2a1f10" stopOpacity=".9"/>
          <stop offset="100%" stopColor="#0f0b08" stopOpacity="0"/>
        </radialGradient>
        <radialGradient id="ink2" cx="80%" cy="70%">
          <stop offset="0%" stopColor="#3a2a1c" stopOpacity=".7"/>
          <stop offset="100%" stopColor="#0f0b08" stopOpacity="0"/>
        </radialGradient>
      </defs>
      <rect width="400" height="400" fill="url(#ink1)"/>
      <rect width="400" height="400" fill="url(#ink2)"/>

      {/* thin frame */}
      <rect x="22" y="22" width="356" height="356" fill="none" stroke="#d8c9a3" strokeOpacity=".25"/>

      {/* top label */}
      <text x="32" y="46" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="4" fill="#d8c9a3" opacity=".8">MUSIC—PENDRAMA</text>
      <text x="368" y="46" textAnchor="end" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="4" fill="#d8c9a3" opacity=".6">VOL. 01</text>

      {/* title */}
      <text x="200" y="210" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900" fontStyle="italic"
            fontSize={title.length > 12 ? 40 : 54} fill="#f0e5cc" letterSpacing="1">
        {title.toUpperCase()}
      </text>
      <text x="200" y="236" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontWeight="700" fontSize="14"
            letterSpacing="8" fill="#9a968f">{album.kr}</text>

      {/* red seal */}
      <g transform="translate(310,300)">
        <rect x="0" y="0" width="50" height="50" fill="#b83030"/>
        <text x="25" y="22" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontWeight="900" fontSize="14" fill="#fdf2e3">劍</text>
        <text x="25" y="40" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontWeight="900" fontSize="14" fill="#fdf2e3">閣</text>
      </g>

      {/* bottom line */}
      <line x1="32" y1="360" x2="280" y2="360" stroke="#d8c9a3" strokeOpacity=".35"/>
      <text x="32" y="374" fontFamily="JetBrains Mono, monospace" fontSize="8" letterSpacing="3" fill="#d8c9a3" opacity=".5">HYEOL·MAENG / OST 01</text>
    </svg>
  );
}

// 2) Grid line — modern fantasy / returner, technical grid look
function Jacket_GridLine({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <defs>
        <pattern id="grid-a" width="20" height="20" patternUnits="userSpaceOnUse">
          <path d="M 20 0 L 0 0 0 20" fill="none" stroke="#6ae3c9" strokeOpacity=".08"/>
        </pattern>
      </defs>
      <rect width="400" height="400" fill="#0a0d14"/>
      <rect width="400" height="400" fill="url(#grid-a)"/>
      {/* cross */}
      <line x1="200" y1="0" x2="200" y2="400" stroke="#6ae3c9" strokeOpacity=".25"/>
      <line x1="0" y1="200" x2="400" y2="200" stroke="#6ae3c9" strokeOpacity=".25"/>
      {/* corner ticks */}
      {[[30,30],[370,30],[30,370],[370,370]].map(([x,y],i)=>(
        <g key={i}>
          <line x1={x-6} y1={y} x2={x+6} y2={y} stroke="#6ae3c9" strokeOpacity=".8"/>
          <line x1={x} y1={y-6} x2={x} y2={y+6} stroke="#6ae3c9" strokeOpacity=".8"/>
        </g>
      ))}
      <text x="30" y="60" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="4" fill="#6ae3c9" opacity=".85">MUSIC—PENDRAMA</text>
      <text x="370" y="60" textAnchor="end" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="3" fill="#6ae3c9" opacity=".7">// LOOP_00</text>

      <text x="200" y="215" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900"
            fontSize={title.length > 12 ? 42 : 56} fill="#e9f7f2" letterSpacing="-1">{title.toUpperCase()}</text>
      <text x="200" y="242" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontWeight="500" fontSize="12"
            letterSpacing="8" fill="#6ae3c9" opacity=".75">{album.kr}</text>

      <text x="30" y="380" fontFamily="JetBrains Mono, monospace" fontSize="8" letterSpacing="3" fill="#6ae3c9" opacity=".6">RET.v01 · ITER 0000</text>
    </svg>
  );
}

// 3) Strata — hunter, layered strata / tower vibe
function Jacket_Strata({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <rect width="400" height="400" fill="#0b0814"/>
      {/* stacked layers */}
      {Array.from({ length: 7 }).map((_, i) => (
        <rect key={i} x="0" y={60 + i * 44} width="400" height="2" fill="#c0d5ff" opacity={0.08 + i*0.05}/>
      ))}
      {/* vertical shaft */}
      <rect x="195" y="0" width="10" height="400" fill="#c0d5ff" opacity=".18"/>
      <text x="30" y="44" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="3" fill="#c0d5ff" opacity=".8">MUSIC—PENDRAMA</text>
      <text x="200" y="218" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900" fontStyle="italic"
            fontSize={title.length>12 ? 38 : 50} fill="#e9edff">{title.toUpperCase()}</text>
      <text x="200" y="244" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontSize="13" letterSpacing="6" fill="#c0d5ff" opacity=".7">{album.kr}</text>
      <text x="30" y="378" fontFamily="JetBrains Mono, monospace" fontSize="8" letterSpacing="2" fill="#c0d5ff" opacity=".5">TOWER / FLOOR 07 ASCENT</text>
    </svg>
  );
}

// 4) Bloom — romance, soft vignette + filigree
function Jacket_Bloom({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <defs>
        <radialGradient id="rgo" cx="50%" cy="50%" r="55%">
          <stop offset="0%" stopColor="#3a1a22"/>
          <stop offset="100%" stopColor="#0f0609"/>
        </radialGradient>
      </defs>
      <rect width="400" height="400" fill="url(#rgo)"/>
      {/* concentric dotted rings */}
      {[80,120,160].map((r,i)=>(
        <circle key={i} cx="200" cy="200" r={r} fill="none" stroke="#e8b86b" strokeOpacity={0.3 - i*0.08} strokeDasharray="1 4"/>
      ))}
      <text x="200" y="52" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontStyle="italic" fontSize="11" letterSpacing="6" fill="#e8b86b" opacity=".85">MUSIC · PENDRAMA</text>
      <text x="200" y="212" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="700" fontStyle="italic"
            fontSize={title.length>12 ? 42 : 56} fill="#f6e6cc">{title}</text>
      <text x="200" y="244" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontSize="12" letterSpacing="8" fill="#e8b86b" opacity=".8">{album.kr}</text>
      <line x1="140" y1="280" x2="260" y2="280" stroke="#e8b86b" strokeOpacity=".5"/>
      <text x="200" y="300" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="8" letterSpacing="3" fill="#e8b86b" opacity=".6">DOLCE · VITA · 돌체비타</text>
    </svg>
  );
}

// 5) Ticker — regressor / digital clock
function Jacket_Ticker({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <rect width="400" height="400" fill="#0a0d10"/>
      {/* time strip */}
      <g opacity=".9">
        <text x="40" y="140" fontFamily="JetBrains Mono, monospace" fontSize="60" fill="#c0d5ff" opacity=".08" letterSpacing="4">00:00:00</text>
        <text x="40" y="200" fontFamily="JetBrains Mono, monospace" fontSize="60" fill="#c0d5ff" opacity=".18" letterSpacing="4">17:09:99</text>
        <text x="40" y="260" fontFamily="JetBrains Mono, monospace" fontSize="60" fill="#c0d5ff" opacity=".08" letterSpacing="4">00:00:00</text>
      </g>
      <text x="30" y="44" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="3" fill="#c0d5ff">MUSIC—PENDRAMA · REGRESS</text>
      <text x="30" y="340" fontFamily="Bodoni Moda, serif" fontWeight="900" fontSize={title.length>12 ? 32 : 44} fill="#f0f3ff">{title.toUpperCase()}</text>
      <text x="30" y="366" fontFamily="Noto Serif KR, serif" fontSize="13" letterSpacing="6" fill="#c0d5ff" opacity=".75">{album.kr}</text>
    </svg>
  );
}

// 6) Ring — wuxia / blood lotus
function Jacket_Ring({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <rect width="400" height="400" fill="#0e0505"/>
      <circle cx="200" cy="200" r="160" fill="none" stroke="#b83030" strokeOpacity=".55"/>
      <circle cx="200" cy="200" r="140" fill="none" stroke="#b83030" strokeOpacity=".25" strokeDasharray="2 6"/>
      {/* lotus hint: 8 petals via rotated ellipses */}
      {Array.from({length:8}).map((_,i)=>(
        <ellipse key={i} cx="200" cy="118" rx="12" ry="58" fill="#b83030" fillOpacity=".15"
                 transform={`rotate(${i*45} 200 200)`}/>
      ))}
      <text x="200" y="54" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="4" fill="#e8b86b">MUSIC — PENDRAMA</text>
      <text x="200" y="214" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900" fontStyle="italic"
            fontSize={title.length>12 ? 36 : 48} fill="#f5e6d2">{title.toUpperCase()}</text>
      <text x="200" y="244" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontWeight="700" fontSize="13" letterSpacing="10" fill="#b83030">{album.kr}</text>
    </svg>
  );
}

// 7) Sigil — hunter rune diamond
function Jacket_Sigil({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <rect width="400" height="400" fill="#060910"/>
      <g transform="translate(200,200) rotate(45)">
        <rect x="-110" y="-110" width="220" height="220" fill="none" stroke="#5be8c1" strokeOpacity=".7"/>
        <rect x="-70" y="-70" width="140" height="140" fill="none" stroke="#5be8c1" strokeOpacity=".35"/>
      </g>
      <text x="200" y="52" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="5" fill="#5be8c1">GATE IX — AWAKENED</text>
      <text x="200" y="214" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900"
            fontSize={title.length>12 ? 34 : 46} fill="#e6fff6">{title.toUpperCase()}</text>
      <text x="200" y="240" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontSize="12" letterSpacing="7" fill="#5be8c1" opacity=".8">{album.kr}</text>
      <text x="200" y="372" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="8" letterSpacing="3" fill="#5be8c1" opacity=".6">S-RANK · FLOOR SEAL</text>
    </svg>
  );
}

// 8) Monarch — alt history, crown tile
function Jacket_Monarch({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <rect width="400" height="400" fill="#15100a"/>
      <rect x="40" y="40" width="320" height="320" fill="none" stroke="#d8c9a3" strokeOpacity=".5"/>
      <rect x="56" y="56" width="288" height="288" fill="none" stroke="#d8c9a3" strokeOpacity=".25"/>
      {/* crown silhouette (simple rectangles, no figurative art) */}
      <g transform="translate(200,150)">
        {[-80,-40,0,40,80].map((x,i)=>(
          <rect key={i} x={x-8} y={-20 - (i%2)*12} width="16" height="28 + (i%2)*12" fill="#d8c9a3" opacity=".7"/>
        ))}
        <rect x="-90" y="8" width="180" height="12" fill="#d8c9a3" opacity=".75"/>
      </g>
      <text x="200" y="260" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900" fontStyle="italic"
            fontSize={title.length>12 ? 34 : 44} fill="#f0e5cc">{title.toUpperCase()}</text>
      <text x="200" y="286" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontSize="12" letterSpacing="8" fill="#d8c9a3" opacity=".7">{album.kr}</text>
      <text x="200" y="344" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="8" letterSpacing="3" fill="#d8c9a3" opacity=".55">ORDER V — 오더파이브</text>
    </svg>
  );
}

// 9) Letter — old letter / envelope
function Jacket_Letter({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <rect width="400" height="400" fill="#140a0e"/>
      <rect x="40" y="90" width="320" height="220" fill="#1e0d14" stroke="#e8b86b" strokeOpacity=".6"/>
      {/* envelope flap lines */}
      <line x1="40" y1="90" x2="200" y2="200" stroke="#e8b86b" strokeOpacity=".4"/>
      <line x1="360" y1="90" x2="200" y2="200" stroke="#e8b86b" strokeOpacity=".4"/>
      <circle cx="200" cy="205" r="14" fill="#b83030" opacity=".85"/>
      <text x="200" y="52" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontStyle="italic" fontSize="11" letterSpacing="7" fill="#e8b86b">MUSIC · PENDRAMA</text>
      <text x="200" y="338" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="700" fontStyle="italic"
            fontSize={title.length>12 ? 30 : 40} fill="#f6e6cc">{title}</text>
      <text x="200" y="362" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontSize="12" letterSpacing="8" fill="#e8b86b" opacity=".8">{album.kr}</text>
    </svg>
  );
}

// 10) Crown-of-ash — noir
function Jacket_Crown({ album, title }) {
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{ width:'100%', height:'100%', display:'block' }}>
      <rect width="400" height="400" fill="#070505"/>
      {/* ashes as dots */}
      {Array.from({length:60}).map((_,i)=>{
        const x = (i*37) % 400; const y = (i*53) % 400;
        return <circle key={i} cx={x} cy={y} r={1 + (i%3)*0.5} fill="#c94f4f" opacity={0.25 + (i%5)*0.05}/>;
      })}
      <rect x="60" y="140" width="280" height="2" fill="#c94f4f" opacity=".7"/>
      <text x="200" y="60" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="5" fill="#c94f4f">MUSIC—PENDRAMA · NOIR</text>
      <text x="200" y="218" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900" fontStyle="italic"
            fontSize={title.length>12 ? 34 : 46} fill="#efe3e3" letterSpacing="1">{title.toUpperCase()}</text>
      <text x="200" y="246" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontWeight="700" fontSize="13" letterSpacing="8" fill="#c94f4f">{album.kr}</text>
      <text x="200" y="360" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="8" letterSpacing="3" fill="#c94f4f" opacity=".6">BLACK LEDGER · VOL. 05</text>
    </svg>
  );
}

// Real cover jacket — novel illustration + MP band + typeset title
function Jacket_Photo({ album, title }) {
  const g = GENRES[album.genre] || GENRES.wuxia;
  const accent = album.accent || g.color;
  return (
    <div style={{position:'relative', width:'100%', height:'100%', overflow:'hidden', background:'#000'}}>
      <img src={album.cover} alt={title}
        style={{width:'100%', height:'100%', objectFit:'cover', display:'block',
          filter:'saturate(0.95) contrast(1.02)'}} />
      {/* subtle bottom scrim for legibility */}
      <div style={{position:'absolute', left:0, right:0, bottom:0, height:'45%',
        background:'linear-gradient(180deg, transparent 0%, rgba(0,0,0,0.85) 80%)'}} />
      {/* top label band */}
      <div style={{position:'absolute', top:10, left:10, right:10,
        display:'flex', justifyContent:'space-between', alignItems:'center',
        fontFamily:'JetBrains Mono, monospace', fontSize:9, letterSpacing:3,
        color:accent, textTransform:'uppercase', textShadow:'0 1px 4px rgba(0,0,0,.8)'}}>
        <span>MUSIC—PENDRAMA</span>
        <span>{g.en}</span>
      </div>
      {/* bottom title */}
      <div style={{position:'absolute', left:14, right:14, bottom:12, color:'#fff'}}>
        <div style={{fontFamily:'Bodoni Moda, serif', fontWeight:900, fontStyle:'italic',
          fontSize: title && title.length > 14 ? 18 : 22, lineHeight:1, letterSpacing:0,
          textShadow:'0 2px 8px rgba(0,0,0,.8)'}}>
          {(title || album.id).toUpperCase()}
        </div>
        <div style={{fontFamily:'Noto Serif KR, serif', fontWeight:700, fontSize:10,
          letterSpacing:5, color:accent, marginTop:5, textShadow:'0 1px 4px rgba(0,0,0,.8)'}}>
          {album.kr}
        </div>
      </div>
      {/* hairline frame */}
      <div style={{position:'absolute', inset:0, border:`1px solid ${accent}33`, pointerEvents:'none'}}/>
    </div>
  );
}

const JACKETS = {
  'photo': Jacket_Photo,
  'ink-seal': Jacket_InkSeal,
  'grid-line': Jacket_GridLine,
  'strata': Jacket_Strata,
  'bloom': Jacket_Bloom,
  'ticker': Jacket_Ticker,
  'ring': Jacket_Ring,
  'sigil': Jacket_Sigil,
  'monarch': Jacket_Monarch,
  'letter': Jacket_Letter,
  'crown': Jacket_Crown,
};

function AlbumJacket({ album, title }) {
  const Comp = JACKETS[album.style] || Jacket_InkSeal;
  return <Comp album={album} title={title || album.id} />;
}

// Video thumbnail placeholder (16:9 with genre motif)
function VideoThumbPlaceholder({ title, group, genre, variant = 'mv', cover }) {
  const g = GENRES[genre] || GENRES.wuxia;
  const accent = g.color;
  if (cover) {
    return (
      <div style={{position:'relative', width:'100%', height:'100%', overflow:'hidden', background:'#000'}}>
        <img src={cover} alt={title}
          style={{width:'100%', height:'100%', objectFit:'cover', display:'block',
            filter:'saturate(0.95) contrast(1.05) brightness(0.9)'}} />
        <div style={{position:'absolute', inset:0, background:
          'linear-gradient(90deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.15) 45%, rgba(0,0,0,0.7) 100%)'}}/>
        <div style={{position:'absolute', top:10, left:12, display:'flex', gap:8, alignItems:'center',
          fontFamily:'JetBrains Mono, monospace', fontSize:10, letterSpacing:3, color:'#fff',
          textShadow:'0 1px 4px rgba(0,0,0,.8)'}}>
          <span style={{fontFamily:'Bodoni Moda, serif', fontWeight:900}}>MP</span>
          <span style={{color:accent}}>{variant === 'lyric' ? 'LYRIC' : 'OFFICIAL'}</span>
        </div>
        <div style={{position:'absolute', left:16, right:16, bottom:16, color:'#fff'}}>
          <div style={{fontFamily:'Bodoni Moda, serif', fontWeight:900, fontStyle:'italic',
            fontSize: 34, lineHeight:1, letterSpacing:1, textShadow:'0 2px 10px rgba(0,0,0,.9)'}}>
            {(title.split(' — ')[0] || '').toUpperCase()}
          </div>
          <div style={{fontFamily:'JetBrains Mono, monospace', fontSize:10, letterSpacing:4,
            color:accent, marginTop:6, textShadow:'0 1px 4px rgba(0,0,0,.8)'}}>
            {group} · {variant === 'lyric' ? 'LYRIC VIDEO' : 'M/V'}
          </div>
        </div>
      </div>
    );
  }
  return (
    <svg viewBox="0 0 640 360" preserveAspectRatio="xMidYMid slice" style={{width:'100%', height:'100%', display:'block'}}>
      <defs>
        <linearGradient id={`vg-${genre}`} x1="0" x2="1">
          <stop offset="0" stopColor="#09090c"/>
          <stop offset="1" stopColor="#131319"/>
        </linearGradient>
      </defs>
      <rect width="640" height="360" fill={`url(#vg-${genre})`}/>
      {/* genre-tinted corner */}
      <rect x="0" y="0" width="6" height="360" fill={accent} opacity=".7"/>
      {/* stripes */}
      {Array.from({length:18}).map((_,i)=>(
        <line key={i} x1="0" y1={20+i*20} x2="640" y2={20+i*20} stroke={accent} strokeOpacity={i%3===0 ? .06 : .03}/>
      ))}
      {variant === 'mv' && (
        <g>
          <text x="320" y="170" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontStyle="italic" fontWeight="900"
                fontSize="56" fill="#f1efe9">{title.split(' — ')[0].toUpperCase()}</text>
          <text x="320" y="200" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="11" letterSpacing="6" fill={accent}>{group}</text>
        </g>
      )}
      {variant === 'lyric' && (
        <g>
          <rect x="80" y="130" width="480" height="2" fill={accent} opacity=".4"/>
          <rect x="80" y="200" width="320" height="2" fill={accent} opacity=".2"/>
          <text x="320" y="175" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontStyle="italic" fontWeight="700"
                fontSize="30" fill="#f1efe9">{title.replace(/ Lyric$/, '').toUpperCase()}</text>
          <text x="320" y="230" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="10" letterSpacing="4" fill={accent}>LYRIC VIDEO · {group}</text>
        </g>
      )}
      {/* official watermark */}
      <g transform="translate(20, 20)">
        <text fontFamily="Bodoni Moda, serif" fontWeight="900" fontSize="11" letterSpacing="3" fill="#f1efe9">MP</text>
        <text x="22" y="0" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="3" fill={accent}>OFFICIAL</text>
      </g>
    </svg>
  );
}

// Shorts placeholder (9:16)
function ShortThumbPlaceholder({ title, group, genre, cover }) {
  const g = GENRES[genre] || GENRES.wuxia;
  const accent = g.color;
  if (cover) {
    return (
      <div style={{position:'relative', width:'100%', height:'100%', overflow:'hidden', background:'#000'}}>
        <img src={cover} alt={title}
          style={{width:'100%', height:'100%', objectFit:'cover', display:'block'}} />
        <div style={{position:'absolute', inset:0, background:'linear-gradient(180deg, rgba(0,0,0,0.3) 0%, transparent 40%, rgba(0,0,0,0.75) 100%)'}}/>
        <div style={{position:'absolute', top:10, left:10, fontFamily:'JetBrains Mono, monospace',
          fontSize:9, letterSpacing:3, color:accent, textShadow:'0 1px 4px rgba(0,0,0,.8)'}}>
          MP · SHORT
        </div>
        <div style={{position:'absolute', bottom:14, left:12, right:12, color:'#fff'}}>
          <div style={{fontFamily:'Bodoni Moda, serif', fontWeight:900, fontStyle:'italic',
            fontSize:18, lineHeight:1.1, textShadow:'0 2px 8px rgba(0,0,0,.9)'}}>
            {(title||'').toUpperCase()}
          </div>
          <div style={{fontFamily:'JetBrains Mono, monospace', fontSize:9, letterSpacing:3,
            color:accent, marginTop:5}}>{group}</div>
        </div>
      </div>
    );
  }
  return (
    <svg viewBox="0 0 360 640" preserveAspectRatio="xMidYMid slice" style={{width:'100%', height:'100%', display:'block'}}>
      <rect width="360" height="640" fill="#0a0a0f"/>
      {Array.from({length:40}).map((_,i)=>(
        <circle key={i} cx={(i*57)%360} cy={(i*83)%640} r={1} fill={accent} opacity=".3"/>
      ))}
      <rect x="0" y="560" width="360" height="4" fill={accent} opacity=".6"/>
      <text x="180" y="300" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900" fontStyle="italic"
            fontSize="32" fill="#f1efe9">{(title || '').split(' ').slice(0,2).join(' ').toUpperCase()}</text>
      <text x="180" y="340" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="11" letterSpacing="5" fill={accent}>{group}</text>
      <text x="20" y="30" fontFamily="JetBrains Mono, monospace" fontSize="10" letterSpacing="3" fill={accent}>MP · SHORT</text>
    </svg>
  );
}

// Group cover placeholder (square)
function GroupCover({ group }) {
  const g = GENRES[group.genre] || GENRES.wuxia;
  const accent = g.color;
  if (group.portrait) {
    return (
      <div style={{position:'relative', width:'100%', height:'100%', overflow:'hidden', background:'#000'}}>
        <img src={group.portrait} alt={group.en}
          style={{width:'100%', height:'100%', objectFit:'cover', display:'block',
            filter:'saturate(0.9) contrast(1.03) brightness(0.85)'}} />
        <div style={{position:'absolute', inset:0, background:
          'linear-gradient(180deg, rgba(0,0,0,0.3) 0%, transparent 35%, rgba(0,0,0,0.85) 100%)'}}/>
        <div style={{position:'absolute', top:10, left:12, right:12,
          display:'flex', justifyContent:'space-between',
          fontFamily:'JetBrains Mono, monospace', fontSize:9, letterSpacing:3, color:accent,
          textShadow:'0 1px 4px rgba(0,0,0,.8)'}}>
          <span>MP · GROUP</span>
          <span style={{color:'#fff', opacity:.85}}>{group.tag.toUpperCase()}</span>
        </div>
        <div style={{position:'absolute', left:14, right:14, bottom:14, color:'#fff', textAlign:'center'}}>
          <div style={{fontFamily:'Bodoni Moda, serif', fontWeight:900, fontStyle:'italic',
            fontSize: group.en.length > 10 ? 26 : 36, lineHeight:1, letterSpacing:2,
            textShadow:'0 2px 10px rgba(0,0,0,.9)'}}>
            {group.en}
          </div>
          <div style={{fontFamily:'Noto Serif KR, serif', fontWeight:500, fontSize:11,
            letterSpacing:8, color:accent, marginTop:6, textShadow:'0 1px 4px rgba(0,0,0,.8)'}}>
            {group.kr}
          </div>
        </div>
      </div>
    );
  }
  return (
    <svg viewBox="0 0 400 400" preserveAspectRatio="xMidYMid slice" style={{width:'100%', height:'100%', display:'block'}}>
      <rect width="400" height="400" fill="#0a0a10"/>
      {group.style === 'inked' && (
        <g>
          <circle cx="200" cy="200" r="130" fill="none" stroke={accent} strokeOpacity=".35"/>
          <rect x="100" y="100" width="200" height="200" fill="none" stroke={accent} strokeOpacity=".2" transform="rotate(45 200 200)"/>
        </g>
      )}
      {group.style === 'digital' && (
        <g>
          <rect x="60" y="60" width="280" height="280" fill="none" stroke={accent} strokeOpacity=".4"/>
          <text x="200" y="140" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="64" fill={accent} opacity=".22" letterSpacing="10">00</text>
          <text x="200" y="210" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="64" fill={accent} opacity=".35" letterSpacing="10">17</text>
          <text x="200" y="280" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="64" fill={accent} opacity=".22" letterSpacing="10">99</text>
        </g>
      )}
      {group.style === 'rune' && (
        <g>
          <polygon points="200,60 340,200 200,340 60,200" fill="none" stroke={accent} strokeOpacity=".55"/>
          <polygon points="200,100 300,200 200,300 100,200" fill="none" stroke={accent} strokeOpacity=".3"/>
          <circle cx="200" cy="200" r="30" fill={accent} opacity=".25"/>
        </g>
      )}
      {group.style === 'gilded' && (
        <g>
          {[60,120,180].map((r,i)=>(
            <circle key={i} cx="200" cy="200" r={r} fill="none" stroke={accent} strokeOpacity={.3 - i*.07} strokeDasharray="1 5"/>
          ))}
        </g>
      )}
      {group.style === 'archive' && (
        <g>
          {[80,140,200,260].map((y,i)=>(
            <rect key={i} x="40" y={y} width="320" height="22" fill="none" stroke={accent} strokeOpacity=".3"/>
          ))}
        </g>
      )}

      <text x="200" y="210" textAnchor="middle" fontFamily="Bodoni Moda, serif" fontWeight="900" fontStyle="italic"
            fontSize={group.en.length>10 ? 34 : 46} fill="#f1efe9" letterSpacing="2">{group.en}</text>
      <text x="200" y="238" textAnchor="middle" fontFamily="Noto Serif KR, serif" fontWeight="500" fontSize="12" letterSpacing="8" fill={accent}>{group.kr}</text>
      <text x="20" y="30" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="3" fill={accent} opacity=".8">MP · GROUP</text>
      <text x="380" y="30" textAnchor="end" fontFamily="JetBrains Mono, monospace" fontSize="9" letterSpacing="3" fill={accent} opacity=".6">{group.tag.toUpperCase()}</text>
    </svg>
  );
}

Object.assign(window, { AlbumJacket, StripedPlaceholder, VideoThumbPlaceholder, ShortThumbPlaceholder, GroupCover });
