// Saola — Portfolio cover-art component (reused on landing + all-projects)
function CoverArt({ id, glyph }) {
  const variants = {
    begood: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <defs>
          <pattern id={`grid-${id}`} width="20" height="20" patternUnits="userSpaceOnUse">
            <path d="M 20 0 L 0 0 0 20" fill="none" stroke="#E6EAF0" strokeWidth="1"/>
          </pattern>
        </defs>
        <rect width="600" height="300" fill="#F8F9FC"/>
        <rect width="600" height="300" fill={`url(#grid-${id})`}/>
        {Array.from({length: 24}).map((_, i) => (
          <circle key={i} cx={60 + (i % 8) * 70} cy={80 + Math.floor(i / 8) * 70} r={2 + (i % 4)} fill={i === 11 ? "#3279F9" : "#121317"} opacity={i === 11 ? 1 : 0.5}/>
        ))}
        <line x1="60" y1="80" x2="480" y2="220" stroke="#3279F9" strokeWidth="1" strokeDasharray="4 4"/>
      </svg>
    ),
    singularity: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        {Array.from({length: 6}).map((_, i) => (
          <circle key={i} cx="300" cy="150" r={30 + i * 22} fill="none" stroke="rgba(255,255,255,0.18)" strokeWidth="1"/>
        ))}
        <circle cx="300" cy="150" r="14" fill="#3279F9"/>
        <text x="50" y="40" fill="rgba(255,255,255,0.6)" fontFamily="ui-monospace, monospace" fontSize="11">zk · institutional · privacy</text>
      </svg>
    ),
    gohub: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        <path d="M0,180 Q150,80 300,180 T600,180" fill="none" stroke="#121317" strokeWidth="1.5"/>
        <path d="M0,200 Q150,100 300,200 T600,200" fill="none" stroke="#3279F9" strokeWidth="1.5"/>
        {[80, 180, 280, 380, 480].map((x, i) => (
          <g key={i}><circle cx={x} cy={i % 2 ? 170 : 130} r="4" fill="#121317"/><text x={x+8} y={i % 2 ? 174 : 134} fontFamily="ui-monospace, monospace" fontSize="10" fill="#45474D">{["SG","JP","US","DE","AU"][i]}</text></g>
        ))}
      </svg>
    ),
    flow: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        {Array.from({length: 5}).map((_, i) => (
          <rect key={i} x={60 + i*100} y={80} width="60" height="140" fill="none" stroke="#121317" strokeWidth="1"/>
        ))}
        <line x1="60" y1="80" x2="520" y2="80" stroke="#3279F9" strokeWidth="2"/>
        {[0,1,2,3,4].map(i => <circle key={i} cx={90+i*100} cy={80} r="4" fill="#3279F9"/>)}
        <text x="60" y="260" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">N-OF-M APPROVAL · MULTI-CHAIN</text>
      </svg>
    ),
    esri: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        <path d="M50,200 Q150,140 220,180 T380,160 T560,140" stroke="#3279F9" strokeWidth="1.5" fill="none"/>
        <path d="M50,220 Q150,170 220,210 T380,190 T560,170" stroke="#121317" strokeWidth="1" fill="none" opacity="0.5"/>
        {Array.from({length: 40}).map((_, i) => (
          <rect key={i} x={(i%10)*60} y={Math.floor(i/10)*30+40} width="4" height="4" fill="#45474D" opacity={((i*37)%10)/25 + 0.1}/>
        ))}
      </svg>
    ),
    bidup: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        <rect x="60" y="60" width="200" height="180" rx="8" fill="#212226" stroke="rgba(255,255,255,0.1)"/>
        <circle cx="160" cy="120" r="3" fill="#FF0000"/><text x="172" y="124" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="10">LIVE</text>
        <rect x="290" y="80" width="240" height="40" rx="6" fill="#3279F9"/>
        <text x="306" y="106" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="13">BID  $1,247</text>
        <rect x="290" y="130" width="240" height="24" rx="4" fill="rgba(255,255,255,0.06)"/>
        <rect x="290" y="162" width="180" height="24" rx="4" fill="rgba(255,255,255,0.06)"/>
        <rect x="290" y="194" width="220" height="24" rx="4" fill="rgba(255,255,255,0.06)"/>
      </svg>
    ),
    tayo: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        <g transform="translate(60, 60)">
          <rect width="180" height="180" fill="none" stroke="#121317" strokeWidth="1"/>
          {Array.from({length: 36}).map((_, i) => (
            <rect key={i} x={(i%6)*30} y={Math.floor(i/6)*30} width="30" height="30" fill={i < 14 ? "#3279F9" : "transparent"} opacity={i < 14 ? 0.18 + (i/36)*0.6 : 1} stroke="#E1E6EC" strokeWidth="0.5"/>
          ))}
        </g>
        <text x="280" y="100" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">FRACTIONS OWNED</text>
        <text x="280" y="130" fontFamily="ui-monospace, monospace" fontSize="36" fill="#121317" fontWeight="500">38.9%</text>
        <text x="280" y="170" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">ERC-1155 · BSC</text>
      </svg>
    ),
    node: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        {[[120,80],[200,150],[300,90],[400,140],[480,80],[150,220],[260,240],[380,220],[470,200]].map(([x,y], i) => (
          <g key={i}>
            {[[120,80],[200,150],[300,90],[400,140],[480,80],[150,220],[260,240],[380,220],[470,200]].map(([x2,y2], j) => j > i && Math.hypot(x2-x, y2-y) < 130 ? <line key={j} x1={x} y1={y} x2={x2} y2={y2} stroke="#3279F9" strokeWidth="0.5" opacity="0.4"/> : null)}
            <circle cx={x} cy={y} r={i===4 ? 8 : 5} fill={i===4 ? "#3279F9" : "#121317"}/>
          </g>
        ))}
      </svg>
    ),
    membots: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        <circle cx="180" cy="150" r="70" fill="none" stroke="#3279F9" strokeWidth="1.2"/>
        <circle cx="180" cy="150" r="44" fill="none" stroke="rgba(255,255,255,0.25)" strokeWidth="1"/>
        <circle cx="180" cy="150" r="18" fill="#3279F9"/>
        <text x="300" y="120" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="13">MEMECOIN.AI</text>
        <text x="300" y="146" fill="rgba(255,255,255,0.6)" fontFamily="ui-monospace, monospace" fontSize="11">MINT IN 2 MIN · GAS-FREE</text>
        <rect x="300" y="170" width="220" height="36" rx="6" fill="rgba(50,121,249,0.18)" stroke="#3279F9"/>
        <text x="320" y="193" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="12">LAUNCH ON UNISWAP →</text>
      </svg>
    ),
    mudigital: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        {Array.from({length: 30}).map((_, i) => (
          <rect key={i} x={40 + i*18} y={220 - (((i*13)%9)+1)*16} width="12" height={(((i*13)%9)+1)*16} fill={i % 6 === 0 ? "#3279F9" : "#121317"} opacity={i % 6 === 0 ? 0.9 : 0.4}/>
        ))}
        <line x1="40" y1="220" x2="580" y2="220" stroke="#121317" strokeWidth="1"/>
        <text x="40" y="50" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">muBOND · YIELD</text>
        <text x="40" y="80" fontFamily="ui-monospace, monospace" fontSize="32" fill="#121317" fontWeight="500">5.42% APY</text>
      </svg>
    ),
    livein: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        {[[80,80],[200,80],[320,80],[440,80],[80,180],[200,180],[320,180],[440,180]].map(([x,y], i) => (
          <g key={i}>
            <rect x={x} y={y} width="80" height="80" fill="#fff" stroke="#E1E6EC"/>
            <rect x={x+10} y={y+30} width="60" height="40" fill={i === 2 ? "#3279F9" : "#121317"} opacity={i === 2 ? 1 : 0.15}/>
            <polygon points={`${x+10},${y+30} ${x+40},${y+10} ${x+70},${y+30}`} fill={i === 2 ? "#3279F9" : "#45474D"} opacity={i === 2 ? 1 : 0.4}/>
          </g>
        ))}
      </svg>
    ),
    nodewars: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        <polygon points="300,40 360,150 300,260 240,150" fill="none" stroke="#3279F9" strokeWidth="1.5"/>
        <polygon points="300,80 340,150 300,220 260,150" fill="rgba(50,121,249,0.2)"/>
        <circle cx="300" cy="150" r="8" fill="#3279F9"/>
        <text x="50" y="40" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="11">LIVES · LEVELS · LEADERBOARD</text>
        {[1,2,3,4,5].map(i => <rect key={i} x={50 + i*20} y={260} width="14" height="14" fill="rgba(50,121,249,0.4)"/>)}
      </svg>
    ),
    ordinals: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        <g transform="translate(200, 80)">
          {Array.from({length: 64}).map((_, i) => (
            <rect key={i} x={(i%8)*22} y={Math.floor(i/8)*22} width="20" height="20" fill={[0,3,8,11,17,22,28,33,41,49,55,60].includes(i) ? "#3279F9" : "#121317"} opacity={[0,3,8,11,17,22,28,33,41,49,55,60].includes(i) ? 1 : 0.15}/>
          ))}
        </g>
        <text x="40" y="280" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">BRC-20 · ORDINALS · TAPROOT</text>
      </svg>
    ),
    ukiss: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        <rect x="220" y="60" width="160" height="180" rx="14" fill="#212226" stroke="#3279F9" strokeWidth="1.5"/>
        <circle cx="300" cy="120" r="22" fill="none" stroke="#3279F9" strokeWidth="2"/>
        <rect x="290" y="110" width="20" height="20" fill="#3279F9"/>
        <text x="240" y="180" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="11">HUGWARE</text>
        <text x="240" y="200" fill="rgba(255,255,255,0.5)" fontFamily="ui-monospace, monospace" fontSize="10">SELF-CUSTODY</text>
      </svg>
    ),
    valenspay: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        <rect x="100" y="80" width="280" height="160" rx="12" fill="#121317"/>
        <rect x="100" y="80" width="280" height="40" rx="12" fill="#3279F9"/>
        <text x="120" y="106" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="11">VALENSPAY · BALANCE</text>
        <text x="120" y="160" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="28" fontWeight="500">$12,847.42</text>
        <rect x="120" y="180" width="80" height="40" rx="6" fill="rgba(255,255,255,0.08)"/>
        <rect x="210" y="180" width="80" height="40" rx="6" fill="rgba(255,255,255,0.08)"/>
        <rect x="300" y="180" width="60" height="40" rx="6" fill="rgba(50,121,249,0.3)"/>
        <text x="420" y="120" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">SEND · INVEST · BUY</text>
      </svg>
    ),
    tezza: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        {[[200, 60, "A"], [240, 60, "K"], [280, 60, "Q"], [320, 60, "J"], [360, 60, "10"]].map(([x,y,v], i) => (
          <g key={i} transform={`rotate(${(i-2)*4} ${x+30} ${y+90})`}>
            <rect x={x} y={y} width="60" height="90" rx="6" fill="#fff" stroke="#3279F9"/>
            <text x={x+8} y={y+22} fontFamily="ui-monospace, monospace" fontSize="14" fill="#121317">{v}</text>
            <text x={x+8} y={y+78} fontFamily="ui-monospace, monospace" fontSize="14" fill={i === 2 ? "#3279F9" : "#121317"}>♠</text>
          </g>
        ))}
        <text x="40" y="270" fill="rgba(255,255,255,0.5)" fontFamily="ui-monospace, monospace" fontSize="11">DECENTRALIZED POKER · MONAD</text>
      </svg>
    ),
    detailing: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        {Array.from({length: 9}).map((_, i) => (
          <g key={i}>
            <rect x={60 + (i%3)*170} y={40 + Math.floor(i/3)*80} width="150" height="60" fill="#fff" stroke="#E1E6EC"/>
            <circle cx={80 + (i%3)*170} cy={70 + Math.floor(i/3)*80} r="10" fill={i === 4 ? "#3279F9" : "#121317"} opacity={i === 4 ? 1 : 0.2}/>
            <rect x={100 + (i%3)*170} y={56 + Math.floor(i/3)*80} width="80" height="6" fill="#121317" opacity="0.6"/>
            <rect x={100 + (i%3)*170} y={70 + Math.floor(i/3)*80} width="50" height="6" fill="#45474D" opacity="0.3"/>
          </g>
        ))}
      </svg>
    ),
    vebank: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        <path d="M40,250 L40,80 L130,80 L130,140 L220,140 L220,180 L310,180 L310,110 L400,110 L400,200 L490,200 L490,140 L560,140" stroke="#3279F9" strokeWidth="2" fill="none"/>
        <line x1="40" y1="250" x2="560" y2="250" stroke="#121317" strokeWidth="1"/>
        <text x="40" y="40" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">SUPPLY APY · UTILIZATION</text>
        <text x="450" y="40" fontFamily="ui-monospace, monospace" fontSize="11" fill="#3279F9">↑ 7.34%</text>
      </svg>
    ),
    taro: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        <rect x="60" y="60" width="220" height="180" rx="8" fill="#fff" stroke="#E1E6EC"/>
        <text x="80" y="90" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">SECURITY</text>
        <text x="80" y="118" fontFamily="ui-monospace, monospace" fontSize="20" fill="#121317" fontWeight="500">SERIES A</text>
        <rect x="80" y="140" width="180" height="6" fill="#3279F9"/>
        <rect x="80" y="156" width="120" height="6" fill="#E1E6EC"/>
        <rect x="80" y="172" width="160" height="6" fill="#E1E6EC"/>
        <rect x="320" y="60" width="220" height="180" rx="8" fill="#121317"/>
        <text x="340" y="90" fontFamily="ui-monospace, monospace" fontSize="11" fill="rgba(255,255,255,0.5)">DIVIDEND</text>
        <text x="340" y="120" fontFamily="ui-monospace, monospace" fontSize="22" fill="#3279F9" fontWeight="500">$0.42</text>
        <text x="340" y="142" fontFamily="ui-monospace, monospace" fontSize="11" fill="rgba(255,255,255,0.5)">PER TOKEN · AUTO</text>
      </svg>
    ),
    realcoin: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        <polygon points="120,220 120,100 180,70 240,100 240,220" fill="#fff" stroke="#121317"/>
        <polygon points="240,220 240,140 320,110 400,140 400,220" fill="#fff" stroke="#121317"/>
        <polygon points="400,220 400,90 460,60 520,90 520,220" fill="#3279F9" stroke="#3279F9"/>
        <line x1="60" y1="220" x2="560" y2="220" stroke="#121317"/>
        {[[160,140],[200,140],[160,170],[200,170]].map(([x,y],i)=><rect key={i} x={x} y={y} width="20" height="20" fill="#3279F9" opacity="0.5"/>)}
        <text x="60" y="50" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">REAL ESTATE TOKENIZED · BSC</text>
      </svg>
    ),
    talecity: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        <path d="M40,260 Q120,180 180,200 T300,180 T440,140 T560,160" stroke="#3279F9" strokeWidth="2" fill="none" strokeDasharray="6 4"/>
        {[[40,260],[180,200],[300,180],[440,140],[560,160]].map(([x,y],i)=><g key={i}><circle cx={x} cy={y} r="6" fill={i === 2 ? "#3279F9" : "#121317"}/><circle cx={x} cy={y} r="12" fill="none" stroke={i === 2 ? "#3279F9" : "#121317"} opacity="0.3"/></g>)}
        <text x="40" y="50" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">GPS · AUDIO · ITINERARY</text>
      </svg>
    ),
    greenride: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        {Array.from({length: 12}).map((_, i) => (
          <rect key={i} x={60 + i*40} y={220 - (i+1)*14} width="28" height={(i+1)*14} fill="#3279F9" opacity={0.3 + (i/24)}/>
        ))}
        <text x="60" y="50" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">CO2 SAVED · GREEN TOKENS</text>
        <text x="60" y="80" fontFamily="ui-monospace, monospace" fontSize="28" fill="#121317" fontWeight="500">128.4 kg</text>
      </svg>
    ),
    supershop: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        {["SHOPEE","LAZADA","TIKI"].map((name, i) => (
          <g key={i}>
            <rect x={60 + i*180} y={70} width="140" height="160" rx="8" fill="#fff" stroke="#E1E6EC"/>
            <text x={70 + i*180} y={92} fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">{name}</text>
            <rect x={70 + i*180} y={104} width={70 + i*15} height="6" fill="#3279F9"/>
            <rect x={70 + i*180} y={120} width={90 - i*10} height="6" fill="#121317" opacity="0.2"/>
            <rect x={70 + i*180} y={136} width={60 + i*5} height="6" fill="#121317" opacity="0.2"/>
            <circle cx={75 + i*180} cy={210} r="4" fill="#3279F9"/>
          </g>
        ))}
      </svg>
    ),
    divui: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        {["HÀ NỘI", "ĐÀ NẴNG", "HỘI AN", "PHÚ QUỐC"].map((name, i) => (
          <g key={i}>
            <rect x={60 + i*130} y={80} width="110" height="160" rx="8" fill={i === 1 ? "#3279F9" : "#fff"} stroke={i === 1 ? "#3279F9" : "#E1E6EC"}/>
            <text x={75 + i*130} y={120} fontFamily="ui-monospace, monospace" fontSize="11" fill={i === 1 ? "#fff" : "#121317"}>{name}</text>
            <text x={75 + i*130} y={210} fontFamily="ui-monospace, monospace" fontSize="9" fill={i === 1 ? "rgba(255,255,255,0.8)" : "#45474D"}>FROM $24</text>
          </g>
        ))}
      </svg>
    ),
    gamingdex: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        <path d="M40,250 Q150,150 300,150 T560,90" stroke="#3279F9" strokeWidth="2" fill="none"/>
        <path d="M40,250 Q150,150 300,150 T560,90 L560,250 Z" fill="rgba(50,121,249,0.15)"/>
        <text x="40" y="40" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="11">PEAK TVL</text>
        <text x="40" y="80" fill="#3279F9" fontFamily="ui-monospace, monospace" fontSize="30" fontWeight="500">$1.46B</text>
        <text x="180" y="80" fill="rgba(255,255,255,0.5)" fontFamily="ui-monospace, monospace" fontSize="11">CONCENTRATED LIQUIDITY · 3 TIERS</text>
      </svg>
    ),
    dca: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        {Array.from({length: 14}).map((_, i) => (
          <g key={i}>
            <rect x={50 + i*36} y={250 - 12 - i*8} width="20" height={12 + i*8} fill="#121317" opacity="0.3"/>
            <circle cx={60 + i*36} cy={250 - 12 - i*8} r="4" fill="#3279F9"/>
          </g>
        ))}
        <text x="50" y="50" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">AUTOMATED DCA · 14 WEEKS</text>
        <text x="50" y="80" fontFamily="ui-monospace, monospace" fontSize="22" fill="#121317" fontWeight="500">+18.7%</text>
      </svg>
    ),
    hqxyz: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        <rect x="60" y="80" width="480" height="160" rx="8" fill="#fff" stroke="#E1E6EC"/>
        <text x="80" y="110" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">DATE</text>
        <text x="200" y="110" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">WALLET</text>
        <text x="350" y="110" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">VALUE</text>
        <text x="480" y="110" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">STATUS</text>
        {[0,1,2,3].map(i => (
          <g key={i}>
            <line x1="80" y1={128 + i*26} x2="520" y2={128 + i*26} stroke="#E1E6EC"/>
            <text x="80" y={144 + i*26} fontFamily="ui-monospace, monospace" fontSize="11" fill="#121317">05/{14-i}/26</text>
            <text x="200" y={144 + i*26} fontFamily="ui-monospace, monospace" fontSize="11" fill="#121317">0x42c…f9</text>
            <text x="350" y={144 + i*26} fontFamily="ui-monospace, monospace" fontSize="11" fill="#121317">$1{2-i},{4*i}24</text>
            <circle cx="490" cy={140 + i*26} r="5" fill={i === 0 ? "#3279F9" : "#121317"} opacity={i === 0 ? 1 : 0.3}/>
          </g>
        ))}
      </svg>
    ),
    valens: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        <rect x="60" y="60" width="240" height="40" rx="6" fill="rgba(50,121,249,0.15)" stroke="#3279F9"/>
        <text x="80" y="86" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="12">BTC/USD  $62,840.22  ↑</text>
        {Array.from({length: 6}).map((_,i)=>(
          <g key={i}>
            <rect x="60" y={120 + i*22} width="240" height="2" fill="rgba(255,255,255,0.1)"/>
            <rect x="60" y={120 + i*22} width={140 - i*10} height="14" fill={i % 2 ? "rgba(50,121,249,0.4)" : "rgba(255,0,0,0.3)"}/>
          </g>
        ))}
        <text x="340" y="120" fill="#3279F9" fontFamily="ui-monospace, monospace" fontSize="13">MPC CUSTODY · QREDO</text>
        <text x="340" y="148" fill="rgba(255,255,255,0.5)" fontFamily="ui-monospace, monospace" fontSize="11">MSB-LICENSED · EU</text>
      </svg>
    ),
    ozfinance: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        <circle cx="300" cy="150" r="80" fill="none" stroke="#121317" strokeWidth="1"/>
        <circle cx="300" cy="150" r="55" fill="none" stroke="#3279F9" strokeWidth="1.5" strokeDasharray="8 4"/>
        <circle cx="300" cy="150" r="30" fill="#3279F9"/>
        <text x="300" y="155" fontFamily="ui-monospace, monospace" fontSize="13" fill="#fff" textAnchor="middle">OZ</text>
        {[0, 60, 120, 180, 240, 300].map((deg, i) => {
          const r = 100; const a = deg * Math.PI / 180;
          return <circle key={i} cx={300 + Math.cos(a)*r} cy={150 + Math.sin(a)*r} r="6" fill={i === 2 ? "#3279F9" : "#121317"}/>;
        })}
      </svg>
    ),
    scalema: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        <text x="60" y="60" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">SOL: contracts/Listing.sol</text>
        {[0,1,2,3,4,5,6].map(i => (
          <g key={i}>
            <text x="60" y={100 + i*22} fontFamily="ui-monospace, monospace" fontSize="11" fill={i % 3 === 0 ? "#3279F9" : "#121317"} opacity={i % 3 === 0 ? 1 : 0.7}>
              {["function list(uint256 id) external {","  require(msg.sender == owner);","  fees[id] = listingFee;","  emit Listed(id);","}","","mapping(uint256 => uint256) fees;"][i]}
            </text>
          </g>
        ))}
      </svg>
    ),
    mwell: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#121317"/>
        <path d="M40,150 L100,150 L120,90 L150,210 L180,120 L220,150 L560,150" stroke="#3279F9" strokeWidth="2" fill="none"/>
        <text x="40" y="40" fill="#fff" fontFamily="ui-monospace, monospace" fontSize="11">ECG · BPM</text>
        <text x="40" y="80" fill="#3279F9" fontFamily="ui-monospace, monospace" fontSize="30" fontWeight="500">72</text>
        <text x="100" y="80" fill="rgba(255,255,255,0.5)" fontFamily="ui-monospace, monospace" fontSize="11">NORMAL SINUS</text>
      </svg>
    ),
    tkt: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#EFF2F7"/>
        <rect x="80" y="70" width="440" height="160" rx="12" fill="#fff" stroke="#E1E6EC"/>
        <line x1="380" y1="70" x2="380" y2="230" stroke="#E1E6EC" strokeDasharray="4 4"/>
        <text x="100" y="100" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">EVENT</text>
        <text x="100" y="130" fontFamily="ui-monospace, monospace" fontSize="18" fill="#121317" fontWeight="500">TKT · LIVE</text>
        <text x="100" y="160" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">SEAT  A24</text>
        <text x="100" y="180" fontFamily="ui-monospace, monospace" fontSize="11" fill="#45474D">PRICE $48.00</text>
        {Array.from({length: 18}).map((_,i)=><rect key={i} x={400 + (i%3)*30} y={90 + Math.floor(i/3)*22} width="20" height={i % 2 ? 14 : 18} fill="#121317" opacity="0.8"/>)}
        <circle cx="450" cy="210" r="6" fill="#3279F9"/>
      </svg>
    ),
    nongsan: (
      <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
        <rect width="600" height="300" fill="#F8F9FC"/>
        {Array.from({length: 12}).map((_, i) => (
          <g key={i}>
            <rect x={60 + (i%4)*130} y={50 + Math.floor(i/4)*78} width="110" height="60" rx="6" fill="#fff" stroke="#E1E6EC"/>
            <circle cx={80 + (i%4)*130} cy={80 + Math.floor(i/4)*78} r="10" fill={[2,5,8].includes(i) ? "#3279F9" : "#121317"} opacity={[2,5,8].includes(i) ? 1 : 0.2}/>
            <rect x={100 + (i%4)*130} y={66 + Math.floor(i/4)*78} width="60" height="5" fill="#121317" opacity="0.6"/>
            <rect x={100 + (i%4)*130} y={80 + Math.floor(i/4)*78} width="40" height="5" fill="#45474D" opacity="0.3"/>
          </g>
        ))}
      </svg>
    ),
  };

  if (variants[id]) return variants[id];
  // Procedural fallback: deterministic dot field by string hash
  let h = 0; for (const c of id) h = ((h << 5) - h + c.charCodeAt(0)) | 0;
  const seeded = (n) => { h = (h * 9301 + 49297) % 233280; return h / 233280; };
  const pts = Array.from({length: 36}).map(() => [Math.floor(seeded()*9), Math.floor(seeded()*5)]);
  return (
    <svg width="100%" height="100%" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid slice">
      <rect width="600" height="300" fill="#F8F9FC"/>
      {pts.map(([x,y], i) => (
        <circle key={i} cx={50 + x*60} cy={40 + y*60} r={3 + (i % 3)} fill={i === 7 ? "#3279F9" : "#121317"} opacity={i === 7 ? 1 : 0.4}/>
      ))}
      <text x="50" y="280" fontFamily="ui-monospace, monospace" fontSize="14" fill="#121317" fontWeight="500">{glyph}</text>
    </svg>
  );
}

window.CoverArt = CoverArt;
