// =============================================================================
// VITRINE DE ANIMAIS — cachorros e bichos de fazenda dentro da Z Shop
// =============================================================================
// Mesmo layout master-detail da Concessionária (`carshop.jsx`):
//   ESQUERDA = os cards da seção (3D girando, borda na cor da raridade)
//   DIREITA  = palco do selecionado (3D grande, ficha com barras, botão de compra)
//
// 🔑 NADA de tabela de bicho aqui. Modelo, barras e etiquetas vêm do
// `metadata` do produto (igual `carshop.jsx` lê `metadata.model`). Duplicar a
// tabela no JS é o erro que já mordeu o projeto: a UI passa a mentir no dia em
// que o banco muda.
//
// A fazenda vende macho e fêmea como produtos SEPARADOS (no PZ o sexo é o tipo do
// animal). Pra não virar uma parede de 10 cards, os dois se juntam num card só e
// viram um botão de escolha no palco — `metadata.par` é quem liga um no outro.
// =============================================================================

const AN_RARIDADE = {
  comum:    { label: 'COMUM',    cor: '#B2B2B2' },
  incomum:  { label: 'INCOMUM',  cor: '#4CE64C' },
  raro:     { label: 'RARO',     cor: '#3075FF' },
  epico:    { label: 'EPICO',    cor: '#B34CE6' },
  lendario: { label: 'LENDARIO', cor: '#FFA000' },
};
function anRar(r) { return AN_RARIDADE[r] || { label: (r || '').toUpperCase(), cor: '#B2B2B2' }; }
function anFmt(n) { return Number(n || 0).toLocaleString('pt-BR'); }

// rótulo de cada barra, por tipo de bicho
const AN_BARRAS = {
  dog:  [['combate', 'COMBATE'], ['faro', 'FARO'], ['carga', 'CARGA'],
         ['obediencia', 'OBEDIENCIA'], ['humor', 'HUMOR']],
  farm: [['leite', 'LEITE'], ['ovo', 'OVO'], ['la', 'LA'],
         ['carne', 'CARNE'], ['porte', 'PORTE']],
};

// --- FICHA: pictogramas ------------------------------------------------------
// A barra diz QUANTO; a ficha diz O QUE. `metadata.ficha` é uma lista de
// { ic, hi, sub }: pictograma, manchete com o número medido, e a frase que explica
// o que aquilo significa jogando.
//
// 🔑 A fonte é o `balance_animais.py` — nada de tabela de bicho aqui, mesma regra
// do resto do arquivo. Estes SVG são só o desenho; se a ficha citar um `ic` que não
// está neste mapa, `gerar_sql_animais.py` (R10) reprova antes de virar migration —
// ícone desconhecido não quebraria a página, desenharia um quadrado vazio.
//
// Traço em `currentColor` num grid 24x24, iguais aos do `GZ_ICONE` do store.jsx.
const AN_PATA = '<circle cx="7" cy="9.2" r="1.7"/><circle cx="11.2" cy="6.6" r="1.7"/>'
  + '<circle cx="15.6" cy="7.4" r="1.7"/><circle cx="18.6" cy="11" r="1.7"/>'
  + '<path d="M9.6 14.2c-1.9 1.5-2.4 4-1 5.2 1.2 1.1 2.8-.3 4.6-.3s3.4 1.4 4.6.3'
  + 'c1.4-1.2.9-3.7-1-5.2-1.2-1-2.3-1.5-3.6-1.5s-2.4.5-3.6 1.5z"/>';

const AN_ICONE = {
  mordida:     '<path d="M13 2 4 13h7l-1 9 9-11h-7l1-9z"/>',
  finaliza:    '<path d="M12 3a7 7 0 0 0-7 7c0 2 .9 3.4 2 4.4V19a1 1 0 0 0 1 1h8'
               + 'a1 1 0 0 0 1-1v-4.6c1.1-1 2-2.4 2-4.4a7 7 0 0 0-7-7z"/>'
               + '<circle cx="9.3" cy="10.2" r="1.3"/><circle cx="14.7" cy="10.2" r="1.3"/>',
  aviso:       '<path d="M2.5 12S6 5.8 12 5.8 21.5 12 21.5 12 18 18.2 12 18.2 2.5 12 2.5 12z"/>'
               + '<circle cx="12" cy="12" r="2.6"/>',
  alforje:     '<path d="M6 20V10.5a6 6 0 0 1 12 0V20a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2z"/>'
               + '<path d="M9.5 6.6V5.2a2.5 2.5 0 0 1 5 0v1.4"/><path d="M8.5 14h7"/>',
  aguenta:     '<path d="M12 2.5 4.5 5.3V11c0 4.8 3.2 8.2 7.5 10.5 4.3-2.3 7.5-5.7 7.5-10.5V5.3L12 2.5z"/>',
  aprende:     '<path d="M12 3.2 2.8 7.3 12 11.4l9.2-4.1L12 3.2z"/>'
               + '<path d="M6.4 9.4V15c0 1.6 2.5 3 5.6 3s5.6-1.4 5.6-3V9.4"/>',
  sentinela:   '<circle cx="12" cy="12" r="2.4"/>'
               + '<path d="M7.4 7.4a6.5 6.5 0 0 0 0 9.2"/><path d="M16.6 16.6a6.5 6.5 0 0 0 0-9.2"/>'
               + '<path d="M4.6 4.6a10.5 10.5 0 0 0 0 14.8"/><path d="M19.4 19.4a10.5 10.5 0 0 0 0-14.8"/>',
  come:        '<path d="M3.2 11.6h17.6a8.8 8.8 0 0 1-17.6 0z"/>'
               + '<path d="M13 8.6c0-1.7 1.3-2.4 1.3-3.6"/><path d="M9.6 8.6c0-1.3.9-1.9.9-2.8"/>',
  resistencia: '<path d="M3 12.5h3.6L9 6.2l3.4 11.6 2.2-5.3H21"/>',
  ninhada:     AN_PATA,
  cria:        AN_PATA,
  produz:      '<path d="M9.2 3h5.6v2.8l2 3.1V20a2 2 0 0 1-2 2H9.2a2 2 0 0 1-2-2V8.9l2-3.1V3z"/>'
               + '<path d="M7.2 13.4h9.6"/>',
  carne:       '<circle cx="12" cy="12" r="8.4"/><circle cx="12" cy="12" r="3.2"/>',
  consumo:     '<path d="M12 21V9.2"/>'
               + '<path d="M12 9.2c0-2-1.5-3.6-3.6-4.1 0 2 1.5 3.6 3.6 4.1z"/>'
               + '<path d="M12 9.2c0-2 1.5-3.6 3.6-4.1 0 2-1.5 3.6-3.6 4.1z"/>'
               + '<path d="M12 14.6c0-2-1.5-3.6-3.6-4.1 0 2 1.5 3.6 3.6 4.1z"/>'
               + '<path d="M12 14.6c0-2 1.5-3.6 3.6-4.1 0 2-1.5 3.6-3.6 4.1z"/>',
  recinto:     '<path d="M4 9.4h16"/><path d="M4 14.4h16"/>'
               + '<path d="M7.2 5v15"/><path d="M12 5v15"/><path d="M16.8 5v15"/>',
  jeito:       '<circle cx="12" cy="12" r="8.6"/><path d="M12 11.4v5"/><path d="M12 7.9v.2"/>',
};

// O rótulo do bloco é o que ele RESPONDE. 🧯 Era "FICHA TÉCNICA · MEDIDA NO MOD" e
// ele cortou os dois pedaços em 30/08: o comprador não quer saber de onde saiu o
// número, quer saber o que o bicho faz.
const AN_ROTULO_FICHA = { dog: 'O QUE ELE FAZ', cat: 'O QUE ELE FAZ', farm: 'O QUE ELE ENTREGA' };

function AnFicha({ itens, cor, tipo }) {
  if (!itens || !itens.length) return null;
  return (
    <div>
      <div style={{
        fontFamily: 'Share Tech Mono', fontSize: 10, color: 'rgba(255,255,255,.6)',
        letterSpacing: '.14em', marginBottom: 10,
      }}>{AN_ROTULO_FICHA[tipo] || AN_ROTULO_FICHA.farm}</div>
      <div className="gz-an-ficha">
        {itens.map((it, i) => (
          <div className="gz-an-it" key={i}>
            <svg viewBox="0 0 24 24" fill="none" stroke={cor} strokeWidth="1.7"
              strokeLinecap="round" strokeLinejoin="round"
              dangerouslySetInnerHTML={{ __html: AN_ICONE[it.ic] || AN_ICONE.jeito }} />
            <div>
              <b>{it.hi}</b>
              <i>{it.sub}</i>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// --- enquadramento: MEDIR, nunca cravar -------------------------------------
// Os modelos não têm a mesma escala nem de longe: a galinha tem 0,30 de altura e
// a vaca 0,95; entre os cães, Border Collie e Retriever são o DOBRO dos outros.
// Um `camera-target` fixo enquadra um e corta o outro — então a página mede a
// caixa de cada modelo quando ele carrega e mira no centro dela.
// SUBIR = MIRAR MAIS BAIXO: quanto maior o fator, mais baixo o bicho fica no
// quadro. Calibragem aprovada pelo Henrique na prévia: palco 0.80, card 0.90.
const AN_OLHAR_PALCO = 0.80;
const AN_OLHAR_CARD = 0.90;

// --- de que lado o bicho está virado ----------------------------------------
// 🚨 MEDIDO em 31/08, prancha de contato com os modelos reais: os pacotes de cão
// (os 5 antigos e os 6 novos) e o de gato apontam pro lado OPOSTO ao dos bichos
// de fazenda. Com um ângulo só, uma das duas seções abre mostrando a traseira do
// animal — e era a de COMPANHEIROS, desde que a loja subiu em 22/08.
//
// Não dá pra consertar no modelo sem re-assar os 16 e trocar as URLs; o ângulo é
// da CÂMERA, então mora aqui. `tipo` já chega em toda chamada.
//
// Isto muda só o quadro INICIAL: os dois model-viewer têm `auto-rotate`, então o
// bicho gira de qualquer jeito. O que muda é qual lado te cumprimenta.
const AN_ANGULO = {
  dog:  { card: '43deg 77deg 96%',  palco: '45deg 74deg 94%' },
  cat:  { card: '43deg 77deg 96%',  palco: '45deg 74deg 94%' },
  farm: { card: '223deg 77deg 96%', palco: '225deg 74deg 94%' },
};
function anAngulo(tipo, onde) {
  return (AN_ANGULO[tipo] || AN_ANGULO.farm)[onde];
}

function anMirar(mv, fator) {
  if (!mv || mv._genzMirado) return;
  mv._genzMirado = true;
  mv.addEventListener('load', () => {
    try {
      const c = mv.getBoundingBoxCenter();
      mv.cameraTarget = `${c.x.toFixed(3)}m ${(c.y * fator).toFixed(3)}m ${c.z.toFixed(3)}m`;
      mv.jumpCameraToGoal();
    } catch (e) { /* sem caixa ainda: o padrão do model-viewer já centraliza */ }
  });
}

// --- agrupa variações num card só -------------------------------------------
// Devolve [{ base, par, variantes }]:
//   `base`      = o card mostrado na lista;
//   `par`       = o outro sexo (fazenda), ou null;
//   `variantes` = lista com 2+ produtos que são o MESMO produto com uma escolha de
//                 aparência (as 5 pelagens do gato), ou null.
//
// 🔑 São dois eixos diferentes, e nenhum substitui o outro. `par` é macho x fêmea:
// no PZ o sexo É O TIPO do animal, e os dois entregam bichos que fazem coisas
// diferentes (só a fêmea produz). `variantes` é pura aparência: mesmo preço, mesmos
// números, muda só a cor. Misturar os dois num campo só faria a vitrine prometer
// que a cor muda o bicho, ou que o macho é uma cor da fêmea.
function anAgrupar(produtos) {
  const porSku = {};
  produtos.forEach(p => { porSku[p.sku] = p; });
  const usados = {};
  const saida = [];
  produtos.forEach(p => {
    if (usados[p.sku]) return;
    const m = p.metadata || {};

    // grupo de aparência: junta TODOS os que declaram o mesmo `metadata.grupo`
    if (m.grupo) {
      const irmaos = produtos.filter(x => (x.metadata || {}).grupo === m.grupo);
      irmaos.forEach(x => { usados[x.sku] = true; });
      saida.push({ base: irmaos[0], par: null, variantes: irmaos.length > 1 ? irmaos : null });
      return;
    }

    const par = m.par ? porSku[m.par] : null;
    // fêmea manda no card; sem sexo declarado (cachorro), manda o próprio
    const femea = (m.sexo === 'macho' && par) ? par : p;
    const macho = (femea === p) ? par : p;
    usados[femea.sku] = true;
    if (macho) usados[macho.sku] = true;
    saida.push({ base: femea, par: macho || null, variantes: null });
  });
  return saida;
}

// Botão de escolha do palco (sexo ou aparência). Mora numa função só porque os dois
// seletores TÊM que parecer o mesmo controle: quando eram dois blocos copiados, o
// primeiro ajuste de estilo deixava um diferente do outro.
function anBotaoOpcao(ligado, cor) {
  return {
    padding: '9px 16px', fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 12,
    letterSpacing: '.08em', textTransform: 'uppercase', cursor: 'pointer',
    background: ligado ? cor + '22' : 'rgba(255,255,255,.03)',
    border: ligado ? `1px solid ${cor}` : '1px solid rgba(255,255,255,.14)',
    color: ligado ? '#fff' : 'rgba(255,255,255,.55)',
    clipPath: 'polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px))',
  };
}

// Borda do card: 3px em cima na cor da raridade, 1px nos outros lados.
// 🪤 Escrita em LONGHAND de proposito. `border` + `borderTop` no mesmo objeto de
// estilo faz o React avisar "mixing shorthand and non-shorthand" -- e o aviso e'
// legitimo: numa re-renderizacao a ordem nao e' garantida e a borda pode ficar
// com a cor do card anterior.
function anBorda(cor, selecionado) {
  const lado = selecionado ? cor : cor + '33';
  return {
    borderStyle: 'solid',
    borderTopWidth: 3, borderRightWidth: 1, borderBottomWidth: 1, borderLeftWidth: 1,
    borderTopColor: cor, borderRightColor: lado, borderBottomColor: lado, borderLeftColor: lado,
  };
}

// --- card da lista ----------------------------------------------------------
function AnimalCard({ grupo, selected, onSelect }) {
  const p = grupo.base;
  const r = anRar(p.rarity);
  const md = p.metadata || {};
  // 🔑 O lado pra onde o bicho olha sai do PRÓPRIO produto (`metadata.kind`), não
  // de uma prop vinda da seção. Um card sabe o que ele é; prop encadeada quebra
  // calada no dia em que alguém montar o card em outro lugar.
  const tipo = md.kind || 'farm';
  const ref = React.useRef(null);

  // tilt 3D + brilho seguindo o mouse — os mesmos números do `carshop.jsx`
  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const b = el.getBoundingClientRect();
    const px = (e.clientX - b.left) / b.width;
    const py = (e.clientY - b.top) / b.height;
    const MAX = 8;
    el.style.transform = `rotateX(${((0.5 - py) * 2 * MAX).toFixed(2)}deg) rotateY(${((px - 0.5) * 2 * MAX).toFixed(2)}deg) scale(1.03)`;
    el.style.setProperty('--gx', (px * 100).toFixed(1) + '%');
    el.style.setProperty('--gy', (py * 100).toFixed(1) + '%');
  };
  const reset = () => { if (ref.current) ref.current.style.transform = 'rotateX(0deg) rotateY(0deg) scale(1)'; };

  return (
    <div className="gz-cs-item" style={{ perspective: 900 }} onClick={() => onSelect(p.sku)}>
      <div ref={ref} onMouseMove={onMove} onMouseLeave={reset} style={{
        position: 'relative', display: 'flex', flexDirection: 'column', height: '100%',
        transformStyle: 'preserve-3d', willChange: 'transform', transition: 'transform .25s ease',
        background: `linear-gradient(165deg, ${r.cor}26 0%, #202020 55%, #1a1a1a 100%)`,
        ...anBorda(r.cor, selected),
        boxShadow: selected ? `0 12px 36px ${r.cor}3d` : '0 8px 24px rgba(0,0,0,.35)',
      }}>
        <div style={{
          position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 5,
          background: `radial-gradient(circle at var(--gx,50%) var(--gy,50%), ${r.cor}24 0%, transparent 48%)`,
        }} />
        <div style={{
          position: 'absolute', top: 10, right: 10, zIndex: 6, transform: 'translateZ(34px)',
          background: r.cor + '1c', border: `1px solid ${r.cor}55`, color: r.cor,
          fontFamily: 'Share Tech Mono', fontSize: 9.5, padding: '3px 8px', letterSpacing: '0.12em',
        }}>{r.label}</div>

        <div style={{
          position: 'relative', flex: 1, minHeight: 128, transform: 'translateZ(44px)',
          background: `radial-gradient(ellipse at 50% 80%, ${r.cor}2e 0%, transparent 66%)`,
        }}>
          {md.model ? (
            <model-viewer src={md.model} alt={p.title} loading="lazy"
              animation-name={md.anim || undefined} autoplay={md.anim ? '' : undefined}
              auto-rotate="" auto-rotate-delay="0" rotation-per-second="20deg"
              interaction-prompt="none" shadow-intensity="0.7" exposure="1.05"
              camera-orbit={anAngulo(tipo, "card")}
              ref={el => anMirar(el, AN_OLHAR_CARD)}
              style={{ width: '100%', height: '100%', background: 'transparent' }} />
          ) : (
            <div style={{
              width: '100%', height: '100%', display: 'flex', alignItems: 'center',
              justifyContent: 'center', fontSize: 46, opacity: .5,
            }}>🐾</div>
          )}
        </div>

        <div style={{ padding: '8px 12px 12px', display: 'flex', flexDirection: 'column', gap: 5, flexShrink: 0, transform: 'translateZ(18px)' }}>
          <div style={{
            fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 13.5, textTransform: 'uppercase',
            lineHeight: 1.12, color: selected ? '#fff' : 'rgba(255,255,255,.85)',
          }}>{(grupo.par || grupo.variantes)
            ? (p.metadata || {}).especie || p.title
            : p.title}</div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <span style={{ fontFamily: 'Share Tech Mono', fontSize: 13, color: '#a8ff00' }}>
              {anFmt(p.price_credits)} <span style={{ fontSize: 10, color: 'rgba(255,255,255,.55)' }}>ZB</span>
            </span>
            {selected && <span style={{ color: r.cor, fontFamily: 'Share Tech Mono', fontSize: 12 }}>▸ NO PALCO</span>}
          </div>
        </div>
      </div>
    </div>
  );
}

// --- a vitrine --------------------------------------------------------------
function AnimalShowcase({ produtos, tipo, session, wallet, busy, onBuy, onNavigate }) {
  const { useState } = React;
  const grupos = React.useMemo(() => anAgrupar(produtos || []), [produtos]);
  const [selSku, setSelSku] = useState(grupos.length ? grupos[0].base.sku : null);
  // sexo escolhido no palco, por grupo (só a fazenda tem par)
  const [sexo, setSexo] = useState('femea');
  // aparência escolhida (as 5 pelagens do gato). Guarda o SKU, não o índice: a
  // ordem da lista vem do banco e pode mudar entre um deploy e outro.
  const [varSku, setVarSku] = useState(null);

  if (!grupos.length) return null;

  const grupo = grupos.find(g => g.base.sku === selSku
    || (g.par && g.par.sku === selSku)
    || (g.variantes && g.variantes.some(v => v.sku === selSku))) || grupos[0];
  const variante = grupo.variantes && varSku
    ? grupo.variantes.find(v => v.sku === varSku)
    : null;
  const mostrado = variante || ((sexo === 'macho' && grupo.par) ? grupo.par : grupo.base);
  const md = mostrado.metadata || {};
  const r = anRar(mostrado.rarity);
  const bars = md.bars || null;
  const defsBar = AN_BARRAS[tipo] || AN_BARRAS.farm;
  const canAfford = session && wallet && (wallet.balance || 0) >= mostrado.price_credits;
  const isBusy = busy === mostrado.sku;

  function selecionar(sku) { setSelSku(sku); setSexo('femea'); setVarSku(null); }

  return (
    <div className="gz-cs-wrap">
      <div className="gz-cs-list">
        {grupos.map(g => (
          <AnimalCard key={g.base.sku} grupo={g}
            selected={g.base.sku === grupo.base.sku} onSelect={selecionar} />
        ))}
      </div>

      <div key={mostrado.sku} className="gz-cs-stage-fade" style={{
        position: 'relative', overflow: 'hidden', display: 'flex', flexDirection: 'column',
        background: `linear-gradient(160deg, ${r.cor}20 0%, #1e1e1e 45%, #191919 100%)`,
        ...anBorda(r.cor, true),
        clipPath: 'polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 16px 100%, 0 calc(100% - 16px))',
      }}>
        <div style={{
          position: 'absolute', top: 14, right: 16, zIndex: 3,
          background: r.cor + '1c', border: `1px solid ${r.cor}55`, color: r.cor,
          fontFamily: 'Share Tech Mono', fontSize: 10, padding: '4px 11px', letterSpacing: '0.14em',
        }}>{r.label}</div>

        <div style={{
          position: 'relative', height: 400,
          background: `radial-gradient(ellipse at 50% 82%, ${r.cor}34 0%, transparent 62%)`,
        }}>
          {md.model && (
            <model-viewer key={mostrado.sku} src={md.model} alt={mostrado.title}
              animation-name={md.anim || undefined} autoplay={md.anim ? '' : undefined}
              auto-rotate="" auto-rotate-delay="0" rotation-per-second="8deg"
              camera-controls="" disable-zoom="" disable-pan="" interaction-prompt="none"
              shadow-intensity="1" exposure="1.1"
              camera-orbit={anAngulo(tipo, "palco")} min-camera-orbit="auto auto 55%"
              ref={el => anMirar(el, AN_OLHAR_PALCO)}
              style={{ width: '100%', height: '100%', background: 'transparent' }} />
          )}
          <div style={{
            position: 'absolute', left: 16, bottom: 10, fontFamily: 'Share Tech Mono',
            fontSize: 9.5, color: 'rgba(255,255,255,.5)', letterSpacing: '.14em', pointerEvents: 'none',
          }}>3D · ARRASTE PRA GIRAR</div>
        </div>

        <div style={{ padding: '16px 20px 20px', display: 'flex', flexDirection: 'column', gap: 14, flex: 1 }}>
          <div>
            <div style={{ fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 'clamp(20px,2.4vw,27px)', textTransform: 'uppercase', lineHeight: 1.05 }}>
              {mostrado.title}
            </div>
            {md.tags && md.tags.length > 0 && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
                {md.tags.map(t => (
                  <span key={t} style={{
                    fontFamily: 'Share Tech Mono', fontSize: 10, letterSpacing: '.06em',
                    color: 'rgba(255,255,255,.62)', border: '1px solid rgba(255,255,255,.14)',
                    padding: '2px 8px', textTransform: 'uppercase',
                  }}>{t}</span>
                ))}
              </div>
            )}
          </div>

          <p style={{ fontSize: 13, color: 'rgba(255,255,255,.68)', lineHeight: 1.6, margin: 0 }}>
            {mostrado.description}
          </p>

          {/* aparência: só existe quando o produto declara um grupo (o gato) */}
          {grupo.variantes && (
            <div>
              <div style={{ fontFamily: 'Share Tech Mono', fontSize: 10, color: 'rgba(255,255,255,.6)', letterSpacing: '.14em', marginBottom: 7 }}>
                PELAGEM · MESMO PRECO
              </div>
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                {grupo.variantes.map(v => {
                  const on = (mostrado.sku === v.sku);
                  return (
                    <button className="gzb" key={v.sku} onClick={() => setVarSku(v.sku)}
                      style={anBotaoOpcao(on, r.cor)}>
                      {(v.metadata || {}).variante || v.title}
                    </button>
                  );
                })}
              </div>
              <div style={{ fontFamily: 'Share Tech Mono', fontSize: 10.5, color: 'rgba(255,255,255,.5)', marginTop: 7, lineHeight: 1.6 }}>
                A cor e aparencia: os numeros sao identicos nas cinco.
              </div>
            </div>
          )}

          {/* macho x fêmea: só existe quando o produto declara um par */}
          {grupo.par && (
            <div>
              <div style={{ fontFamily: 'Share Tech Mono', fontSize: 10, color: 'rgba(255,255,255,.6)', letterSpacing: '.14em', marginBottom: 7 }}>
                MACHO OU FEMEA · MESMO PRECO
              </div>
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                {[{ k: 'femea', p: grupo.base }, { k: 'macho', p: grupo.par }].map(op => {
                  const on = (sexo === op.k);
                  return (
                    <button className="gzb" key={op.k} onClick={() => setSexo(op.k)}
                      style={anBotaoOpcao(on, r.cor)}>{op.p.title}</button>
                  );
                })}
              </div>
              <div style={{ fontFamily: 'Share Tech Mono', fontSize: 10.5, color: 'rgba(255,255,255,.5)', marginTop: 7, lineHeight: 1.6 }}>
                {/* 🚨 `metadata.cria === false` existe porque o veado NAO cruza
                    (`canBeDomesticated = false` no jogo). Sem esta guarda a vitrine
                    prometia "pra nascer filhote voce precisa de um macho junto"
                    logo acima de uma ficha dizendo que ele nao cria -- duas frases
                    nossas se contradizendo na mesma tela. */}
                {md.cria === false
                  ? 'Os dois sao troféu: esta especie nao cria, entao macho e femea mudam so a aparencia.'
                  : (sexo === 'macho'
                    ? 'O macho nao produz — ele serve pra sua criacao ter filhote.'
                    : 'E a femea que produz. Pra nascer filhote voce precisa de um macho junto.')}
              </div>
            </div>
          )}

          {bars && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
              {/* Barra em ZERO some. O rotulo da secao e "O QUE ELE ENTREGA": uma
                  barra de LEITE vazia numa galinha diz "entrega leite, so que nada",
                  e foi assim que a porca "deu leite" na loja ate 13/09. Quem nao
                  produz nao ganha linha. */}
              {defsBar.filter(([k]) => Number(bars[k] || 0) > 0).map(([k, lb]) => {
                const v = Math.max(0, Math.min(100, Number(bars[k] || 0)));
                return (
                  <div key={k} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <span style={{ fontFamily: 'Share Tech Mono', fontSize: 9.5, color: 'rgba(255,255,255,.62)', letterSpacing: '.1em', width: 96, flexShrink: 0 }}>{lb}</span>
                    <div style={{ flex: 1, height: 7, background: 'rgba(255,255,255,.07)' }}>
                      <div key={mostrado.sku + k} className="gz-cs-bar-fill" style={{
                        width: v + '%', height: '100%',
                        background: `linear-gradient(90deg, ${r.cor}88, ${r.cor})`,
                      }} />
                    </div>
                    <span style={{ fontFamily: 'Share Tech Mono', fontSize: 10, color: 'rgba(255,255,255,.6)', width: 26, textAlign: 'right', flexShrink: 0 }}>{v}</span>
                  </div>
                );
              })}
            </div>
          )}

          <AnFicha itens={md.ficha} cor={r.cor} tipo={tipo} />

          <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginTop: 'auto', flexWrap: 'wrap' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              {window.ZbIcon ? <window.ZbIcon size={24} /> : null}
              <span style={{ fontFamily: 'Share Tech Mono', fontSize: 28, color: '#a8ff00', lineHeight: 1 }}>{anFmt(mostrado.price_credits)}</span>
              <span style={{ fontSize: 12, color: 'rgba(255,255,255,.5)' }}>ZB</span>
            </div>
            {window.GzSeloValidade ? <window.GzSeloValidade categoria="animal" /> : null}
            <button className="gzb" onClick={() => session ? onBuy(mostrado) : (onNavigate && onNavigate('auth'))} disabled={isBusy} style={{
              flex: '1 1 180px', maxWidth: 320, padding: '14px 22px',
              background: !session ? 'transparent' : (canAfford ? r.cor : 'rgba(255,255,255,.06)'),
              color: !session ? '#a8ff00' : (canAfford ? '#111' : 'rgba(255,255,255,.4)'),
              border: !session ? '1px solid rgba(168,255,0,.4)' : 'none',
              fontFamily: 'Rajdhani', fontWeight: 700, fontSize: 15, letterSpacing: '0.12em',
              cursor: isBusy ? 'wait' : 'pointer', textTransform: 'uppercase', transition: 'all .2s',
              clipPath: 'polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 9px 100%, 0 calc(100% - 9px))',
            }}>
              {!session ? 'Entrar pra comprar' : isBusy ? 'Comprando...' : 'Comprar'}
            </button>
          </div>

          <div style={{ fontFamily: 'Share Tech Mono', fontSize: 10.5, color: 'rgba(255,255,255,.5)', letterSpacing: '.04em', lineHeight: 1.6 }}>
            {tipo === 'dog'
              ? 'Chega uma GenZBall lacrada pelo CORREIO do jogo (F5 › Correio). Abriu, nasce o filhote — já é seu, sem domar.'
              : 'Chega uma GenZBall lacrada pelo CORREIO do jogo (F5 › Correio). Solta onde quiser: nasce reivindicado no seu nome.'}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AnimalShowcase });
