// ViG Command Center — Dragon Center (gallery + assignments + intel drawer)
// Art: ViG emblem set · Data: DRAGONCODEX (evonytools/ViG sheets)
const { useState: useStateDG, useMemo: useMemoDG, useEffect: useEffectDG } = React;

const DG_TROOPS = ['Ground', 'Mounted', 'Ranged', 'Siege'];
const DG_TROOP_COLOR = { Ground: '#2563eb', Mounted: '#dc2626', Ranged: '#16a34a', Siege: '#9333ea' };
const DG_TROOP_IMG = { Ground: 'vig/assets/icons/infantry.png', Mounted: 'vig/assets/icons/cavalry.png', Ranged: 'vig/assets/icons/ranged.png', Siege: 'vig/assets/icons/siege.png' };
const DG_SPEND = [['ftp', 'F2P'], ['low', 'Low spend'], ['med', 'Mid spend'], ['high', 'High spend']];

function dgImg(name) {
  const slug = name === 'Celtic Dragon' ? 'celtic-demon' : name.toLowerCase().replace(/\s+/g, '-');
  return 'vig/assets/dragons/' + slug + '.webp';
}
/* how strongly a dragon serves a troop type — parsed from lv20 buffs + maxed talents */
function dgFocus(d) {
  const out = {};
  const top = d.tiers[d.tiers.length - 1];
  const pools = [[top.buffs, 1], [(d.talents100 || []).flat(), 0.6], [d.talent60 || [], 0.4]];
  DG_TROOPS.forEach(t => {
    let s = 0;
    pools.forEach(([list, w]) => list.forEach(b => {
      if (b.includes(t)) { const m = /([\d.]+)\s*%/.exec(b); s += (m ? +m[1] : 10) * w; }
    }));
    out[t] = Math.round(s);
  });
  return out;
}

const DG_CSS = `
@keyframes dgIn { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes dgGlow { 0%,100% { opacity: .35; } 50% { opacity: .7; } }
@keyframes dgDrawer { from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: none; } }
@keyframes dgFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
.dg-card { animation: dgIn .45s cubic-bezier(.22,1,.36,1) both; position: relative; cursor: pointer;
  background: radial-gradient(120% 90% at 50% 0%, #23252b 0%, #141519 58%, #0c0d10 100%);
  border: 1px solid #2c2e35; border-radius: 16px; overflow: hidden;
  transition: transform .25s cubic-bezier(.22,1,.36,1), border-color .25s, box-shadow .25s; }
.dg-card:hover { transform: translateY(-5px); border-color: rgba(255,107,0,.55); box-shadow: 0 18px 40px -18px rgba(0,0,0,.7), 0 0 0 1px rgba(255,107,0,.25), 0 0 34px -8px rgba(255,107,0,.35); }
.dg-card .dg-halo { position: absolute; inset: -20% -10% 30%; background: radial-gradient(50% 45% at 50% 42%, rgba(255,107,0,.28), transparent 70%); opacity: 0; transition: opacity .3s; pointer-events: none; }
.dg-card:hover .dg-halo { opacity: 1; animation: dgGlow 2.4s ease-in-out infinite; }
.dg-card .dg-shine { position: absolute; top: 0; bottom: 0; width: 55%; left: -70%; transform: skewX(-18deg);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.09), transparent); transition: left .6s ease; pointer-events: none; }
.dg-card:hover .dg-shine { left: 130%; }
.dg-card img.dg-art { transition: transform .45s cubic-bezier(.22,1,.36,1); }
.dg-card:hover img.dg-art { transform: scale(1.08); }
.dg-stripe { position: absolute; top: 0; left: 0; right: 0; height: 3px; z-index: 3; opacity: .9; }
.dg-artwrap { position: relative; aspect-ratio: 4/5; overflow: hidden; }
.dg-artwrap::before { content:''; position:absolute; inset:0; z-index:1;
  background: radial-gradient(80% 55% at 50% 38%, rgba(255,255,255,.06), transparent 70%); }
.dg-scrim { position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(to top, #0a0b0e 4%, rgba(10,11,14,.82) 22%, rgba(10,11,14,.15) 48%, transparent 70%); }
.dg-card .dg-art { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:50% 32%; }
.dg-meter-seg { height:3px; border-radius:3px; flex:1; }
.dg-hex { width:34px; height:38px; display:flex; align-items:center; justify-content:center; clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); font-weight:800; }
.dg-powerbar { height:5px; border-radius:4px; background:rgba(255,255,255,.12); overflow:hidden; }
.dg-assigned-ring { box-shadow: 0 0 0 2px #FF6B00, 0 0 22px -2px rgba(255,107,0,.6); }
.dg-drawer { animation: dgDrawer .32s cubic-bezier(.22,1,.36,1) both; }
.dg-hero-art { animation: dgFloat 4.5s ease-in-out infinite; filter: drop-shadow(0 14px 28px rgba(0,0,0,.6)); }
@media (prefers-reduced-motion: reduce) { .dg-card, .dg-drawer, .dg-hero-art { animation: none !important; } .dg-card:hover { transform: none; } }
`;

/* ---------- assignment slots ---------- */
function DgSlots({ assign, byName, onPick, onClear }) {
  return (
    <div className="grid grid-cols-2 gap-3 lg:grid-cols-4">
      {DG_TROOPS.map(t => {
        const d = assign[t] ? byName[assign[t]] : null;
        return (
          <Card key={t} className="flex items-center gap-3 p-3">
            <img src={DG_TROOP_IMG[t]} alt="" className="h-8 w-8 shrink-0 rounded-lg" />
            <div className="min-w-0 flex-1">
              <div className="text-[10.5px] font-bold uppercase tracking-wider" style={{ color: DG_TROOP_COLOR[t] }}>{t} march</div>
              {d ? <div className="truncate text-[13.5px] font-bold text-zinc-900 dark:text-white">{d.name}</div>
                : <div className="text-[12px] text-zinc-400">No dragon assigned</div>}
            </div>
            {d ? (
              <div className="flex items-center gap-1.5">
                <img src={dgImg(d.name)} alt="" className="h-10 w-7 cursor-pointer rounded-md object-cover object-top" onClick={() => onPick(d)} />
                <button onClick={() => onClear(t)} className="rounded p-0.5 text-zinc-400 hover:text-rose-500" title="Unassign"><Icon name="x" size={13} /></button>
              </div>
            ) : <Icon name="plus" size={16} className="text-zinc-300 dark:text-zinc-600" />}
          </Card>
        );
      })}
    </div>
  );
}

/* ---------- intel drawer ---------- */
function DgDrawer({ d, assign, onAssign, onClose }) {
  const [tierIdx, setTierIdx] = useStateDG(d.tiers.length - 1);
  useEffectDG(() => setTierIdx(d.tiers.length - 1), [d]);
  const tier = d.tiers[tierIdx];
  const focus = dgFocus(d);
  const maxF = Math.max(1, ...Object.values(focus));
  return (
    <div className="fixed inset-0 z-50 flex justify-end">
      <div onClick={onClose} className="absolute inset-0" style={{ background: 'rgba(8,8,10,.6)', backdropFilter: 'blur(3px)' }}></div>
      <div className="dg-drawer relative h-full w-full max-w-md overflow-y-auto bg-white shadow-2xl dark:bg-zinc-900">
        {/* hero */}
        <div className="relative overflow-hidden px-5 pb-5 pt-4" style={{ background: 'radial-gradient(130% 100% at 50% 0%, #26282f 0%, #131418 60%, #0b0c0f 100%)' }}>
          <button onClick={onClose} className="absolute right-3.5 top-3.5 z-10 rounded-lg bg-white/10 p-1.5 text-zinc-300 backdrop-blur hover:bg-white/20 hover:text-white"><Icon name="x" size={16} /></button>
          <div className="pointer-events-none absolute inset-x-0 top-6 mx-auto h-44 w-44 rounded-full" style={{ background: 'radial-gradient(circle, rgba(255,107,0,.3), transparent 70%)' }}></div>
          <img src={dgImg(d.name)} alt={d.name} className="dg-hero-art relative mx-auto h-56 object-contain" />
          <div className="relative mt-2 text-center">
            <div className="text-[20px] font-bold tracking-wide text-white">{d.name}</div>
            <div className="mt-1 flex items-center justify-center gap-2">
              <span className={`rounded-full px-2.5 py-0.5 text-[10.5px] font-bold uppercase tracking-wider ${d.type === 'Elder' ? 'bg-amber-400/15 text-amber-300' : 'bg-zinc-400/15 text-zinc-300'}`}>{d.type} dragon</span>
            </div>
            <div className="mt-1.5 text-[11.5px] text-zinc-400">{d.unlock}</div>
          </div>
        </div>

        <div className="space-y-4 p-5">
          {/* troop focus */}
          <div>
            <div className="mb-1.5 text-[11px] font-bold uppercase tracking-wide text-zinc-400">Troop focus</div>
            <div className="space-y-1.5">
              {DG_TROOPS.filter(t => focus[t] > 0).map(t => (
                <div key={t} className="flex items-center gap-2.5">
                  <img src={DG_TROOP_IMG[t]} alt="" className="h-5 w-5 rounded" />
                  <span className="w-16 text-[11.5px] font-semibold" style={{ color: DG_TROOP_COLOR[t] }}>{t}</span>
                  <div className="h-1.5 flex-1 overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800">
                    <div className="h-full rounded-full transition-all duration-500" style={{ width: (focus[t] / maxF * 100) + '%', background: DG_TROOP_COLOR[t] }}></div>
                  </div>
                  <span className="w-10 text-right text-[11.5px] font-bold tabular-nums text-zinc-500">{focus[t]}</span>
                </div>
              ))}
              {!DG_TROOPS.some(t => focus[t] > 0) && <div className="text-[12px] text-zinc-400">Utility dragon — no direct troop buffs.</div>}
            </div>
          </div>

          {/* tier buffs */}
          <div>
            <div className="mb-1.5 flex items-center justify-between">
              <span className="text-[11px] font-bold uppercase tracking-wide text-zinc-400">Buffs by level</span>
              <Segmented options={d.tiers.map((t, i) => ({ value: i, label: 'Lv' + t.lv }))} value={tierIdx} onChange={setTierIdx} />
            </div>
            <div className="space-y-1.5">
              {tier.buffs.map((b, i) => (
                <div key={i} className="flex items-start gap-2 rounded-lg border border-zinc-100 px-3 py-2 text-[12.5px] text-zinc-700 dark:border-zinc-800 dark:text-zinc-200">
                  <Icon name="bolt" size={13} className="mt-0.5 shrink-0 text-brand" />{b}
                </div>
              ))}
            </div>
            <div className="mt-1.5 text-[11px] text-zinc-400">Dragon stats at Lv{tier.lv}: +{tier.stats[0]} each · Max refines: {String(d.maxRefines).replace('\n', ' · ')}</div>
          </div>

          {/* talents */}
          {d.talents40 && d.talents40.length > 0 && (
            <div>
              <div className="mb-1.5 text-[11px] font-bold uppercase tracking-wide text-zinc-400">Talents · level 40</div>
              <div className="grid grid-cols-1 gap-1.5">
                {d.talents40.map((pair, i) => (
                  <div key={i} className="flex flex-wrap gap-x-3 gap-y-0.5 rounded-lg bg-zinc-50 px-3 py-1.5 text-[12px] text-zinc-600 dark:bg-zinc-800/60 dark:text-zinc-300">
                    {pair.map((p, j) => <span key={j} className="flex items-center gap-1"><span className="h-1 w-1 rounded-full bg-brand"></span>{p}</span>)}
                  </div>
                ))}
              </div>
            </div>
          )}
          {d.talents100 && d.talents100.length > 0 && (
            <div>
              <div className="mb-1.5 text-[11px] font-bold uppercase tracking-wide text-zinc-400">Talents · level 100</div>
              <div className="grid grid-cols-1 gap-1.5">
                {d.talents100.map((pair, i) => (
                  <div key={i} className="flex flex-wrap gap-x-3 gap-y-0.5 rounded-lg border border-brand/25 bg-brand/[0.05] px-3 py-1.5 text-[12px] font-medium text-zinc-700 dark:text-zinc-200">
                    {pair.map((p, j) => <span key={j} className="flex items-center gap-1"><Icon name="star" size={11} className="text-brand" />{p}</span>)}
                  </div>
                ))}
              </div>
            </div>
          )}
          {d.talent60 && d.talent60.length > 0 && (
            <div className="flex flex-wrap items-center gap-x-3 gap-y-1 rounded-lg bg-zinc-50 px-3 py-2 text-[12px] text-zinc-600 dark:bg-zinc-800/60 dark:text-zinc-300">
              <span className="text-[10.5px] font-bold uppercase tracking-wide text-zinc-400">Lv60 talent</span>
              {d.talent60.map((p, j) => <span key={j}>{p}</span>)}
            </div>
          )}

          {/* recommended use */}
          <div>
            <div className="mb-1.5 text-[11px] font-bold uppercase tracking-wide text-zinc-400">Recommended use</div>
            <div className="grid grid-cols-2 gap-1.5">
              {DG_SPEND.map(([k, label]) => (
                <div key={k} className="rounded-lg border border-zinc-100 px-3 py-2 dark:border-zinc-800">
                  <div className="text-[10px] font-bold uppercase tracking-wide text-zinc-400">{label}</div>
                  <div className={`text-[12.5px] font-semibold ${d.uses[k] ? 'text-zinc-800 dark:text-zinc-100' : 'text-zinc-300 dark:text-zinc-600'}`}>{d.uses[k] || '—'}</div>
                </div>
              ))}
            </div>
          </div>

          {/* assign */}
          <div>
            <div className="mb-1.5 text-[11px] font-bold uppercase tracking-wide text-zinc-400">Assign to march</div>
            <div className="grid grid-cols-2 gap-1.5">
              {DG_TROOPS.map(t => {
                const on = assign[t] === d.name;
                return (
                  <button key={t} onClick={() => onAssign(t, on ? null : d.name)}
                    className={`flex items-center justify-center gap-1.5 rounded-lg border px-2 py-2 text-[12.5px] font-semibold transition-colors ${on ? 'border-brand bg-brand text-white' : 'border-zinc-200 text-zinc-600 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800'}`}>
                    {on && <Icon name="check" size={13} />}{t}
                  </button>
                );
              })}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ---------- recommendations ---------- */
function dgBestFor(rows, troop) {
  return rows.slice().sort((a, b) => b.focus[troop] - a.focus[troop]).filter(r => r.focus[troop] > 0);
}
function DgRecommend({ rows, assign, byName, onAssign, onPick }) {
  const [open, setOpen] = useStateDG(() => LS.get('vig2_dg_rec_open', false));
  useEffectDG(() => { LS.set('vig2_dg_rec_open', open); }, [open]);
  const recs = DG_TROOPS.map(t => {
    const ranked = dgBestFor(rows, t);
    return { t, best: ranked[0], runner: ranked[1] };
  });
  const gaps = recs.filter(r => r.best && assign[r.t] !== r.best.d.name);
  return (
    <Card className="overflow-hidden">
      {/* compact one-line strip */}
      <div className="flex items-center gap-2.5 px-3 py-2">
        <Icon name="target" size={15} className="shrink-0 text-brand" />
        <span className="shrink-0 text-[12px] font-bold uppercase tracking-wide text-zinc-900 dark:text-white">Best picks</span>
        {/* inline best-per-troop chips */}
        <div className="flex min-w-0 flex-1 items-center gap-1.5 overflow-x-auto">
          {recs.map(({ t, best }) => best && (
            <button key={t} onClick={() => onPick(best.d)} className="flex shrink-0 items-center gap-1.5 rounded-lg border px-2 py-1 text-[11.5px] transition-colors hover:bg-zinc-50 dark:hover:bg-zinc-800" style={{ borderColor: DG_TROOP_COLOR[t] + '55' }}>
              <img src={DG_TROOP_IMG[t]} alt="" className="h-3.5 w-3.5" />
              <span className="font-semibold text-zinc-700 dark:text-zinc-200">{best.d.name}</span>
              {assign[t] === best.d.name && <Icon name="check" size={11} className="text-emerald-500" stroke={3} />}
            </button>
          ))}
        </div>
        {gaps.length > 0
          ? <button onClick={() => gaps.forEach(r => onAssign(r.t, r.best.d.name))} className="shrink-0 inline-flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-[12px] font-semibold text-white transition-all hover:brightness-110" style={{ background: 'linear-gradient(180deg,#ff7d1a,#FF6B00)', boxShadow: '0 5px 14px -8px rgba(255,107,0,.7)' }}><Icon name="bolt" size={13} />Auto-assign ({gaps.length})</button>
          : <span className="shrink-0 inline-flex items-center gap-1 text-[11.5px] font-semibold text-emerald-500"><Icon name="check" size={12} stroke={3} />Optimal</span>}
        <button onClick={() => setOpen(o => !o)} className="shrink-0 rounded-md p-1 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300" title={open ? 'Hide details' : 'Show details'}><Icon name="chevron" size={15} className={open ? 'rotate-180' : ''} /></button>
      </div>
      {/* expandable detail */}
      {open && (
        <div className="grid grid-cols-1 gap-px border-t border-zinc-100 bg-zinc-100 dark:border-zinc-800 dark:bg-zinc-800 sm:grid-cols-2 lg:grid-cols-4">
          {recs.map(({ t, best, runner }) => {
            const cur = assign[t] ? byName[assign[t]] : null;
            const isBest = cur && best && cur.name === best.d.name;
            return (
              <div key={t} className="bg-white p-3 dark:bg-zinc-900">
                <div className="flex items-center gap-1.5">
                  <img src={DG_TROOP_IMG[t]} alt="" className="h-4 w-4 rounded" />
                  <span className="text-[10.5px] font-bold uppercase tracking-wider" style={{ color: DG_TROOP_COLOR[t] }}>{t}</span>
                </div>
                {best ? (
                  <div className="mt-2 flex items-center gap-2.5">
                    <img src={dgImg(best.d.name)} alt="" className="h-12 w-9 cursor-pointer rounded-md object-cover object-top" onClick={() => onPick(best.d)} />
                    <div className="min-w-0 flex-1">
                      <div className="truncate text-[13px] font-bold text-zinc-900 dark:text-white">{best.d.name}</div>
                      <div className="text-[10.5px] tabular-nums" style={{ color: DG_TROOP_COLOR[t] }}>score {best.focus[t]}{runner ? <span className="text-zinc-400"> · next {runner.d.name.split(' ')[0]} {runner.focus[t]}</span> : null}</div>
                      {isBest
                        ? <div className="mt-1 inline-flex items-center gap-0.5 text-[10.5px] font-semibold text-emerald-500"><Icon name="check" size={11} stroke={3} />Running now</div>
                        : <button onClick={() => onAssign(t, best.d.name)} className="mt-1 inline-flex items-center gap-0.5 rounded-md border border-brand/40 px-1.5 py-0.5 text-[10.5px] font-semibold text-brand hover:bg-brand/10">{cur ? 'Swap in' : 'Assign'}</button>}
                    </div>
                  </div>
                ) : <div className="mt-2 text-[12px] text-zinc-400">No buff dragon</div>}
              </div>
            );
          })}
        </div>
      )}
    </Card>
  );
}

/* ---------- compare modal ---------- */
function DgCompare({ pair, onClose }) {
  const [a, b] = pair;
  const fa = dgFocus(a), fb = dgFocus(b);
  const max = Math.max(1, ...Object.values(fa), ...Object.values(fb));
  const aWins = DG_TROOPS.filter(t => fa[t] > fb[t]).length;
  const bWins = DG_TROOPS.filter(t => fb[t] > fa[t]).length;
  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
      <div onClick={onClose} className="absolute inset-0" style={{ background: 'rgba(8,8,10,.6)', backdropFilter: 'blur(3px)' }}></div>
      <div className="dg-drawer relative w-full max-w-2xl overflow-hidden rounded-2xl bg-white shadow-2xl dark:bg-zinc-900" style={{ maxHeight: '90vh', overflowY: 'auto' }}>
        <div className="grid grid-cols-2">
          {[a, b].map((d, i) => (
            <div key={i} className="relative overflow-hidden px-4 pb-4 pt-5 text-center" style={{ background: 'radial-gradient(120% 100% at 50% 0%, #26282f 0%, #131418 60%, #0b0c0f 100%)' }}>
              <img src={dgImg(d.name)} alt={d.name} className="mx-auto h-32 object-contain" />
              <div className="mt-1.5 text-[15px] font-bold text-white">{d.name}</div>
              <span className={`mt-1 inline-block rounded-full px-2 py-0.5 text-[9.5px] font-bold uppercase tracking-wider ${d.type === 'Elder' ? 'bg-amber-400/15 text-amber-300' : 'bg-zinc-400/15 text-zinc-400'}`}>{d.type}</span>
            </div>
          ))}
        </div>
        <button onClick={onClose} className="absolute right-3 top-3 z-10 rounded-lg bg-white/10 p-1.5 text-zinc-300 backdrop-blur hover:bg-white/20"><Icon name="x" size={16} /></button>
        <div className="p-5">
          <div className="mb-1 flex items-center justify-between text-[11px] font-bold uppercase tracking-wide text-zinc-400">
            <span>{aWins > bWins ? a.name + ' leads' : bWins > aWins ? b.name + ' leads' : 'Even matchup'}</span><span>Troop focus</span>
          </div>
          <div className="space-y-2">
            {DG_TROOPS.map(t => (
              <div key={t} className="flex items-center gap-2">
                <div className="flex flex-1 items-center justify-end gap-2">
                  <span className={`text-[12px] tabular-nums ${fa[t] >= fb[t] && fa[t] > 0 ? 'font-bold text-zinc-900 dark:text-white' : 'text-zinc-400'}`}>{fa[t] || '—'}</span>
                  <div className="h-2 w-full max-w-[110px] overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800"><div className="ml-auto h-full rounded-full" style={{ width: (fa[t] / max * 100) + '%', background: DG_TROOP_COLOR[t] }}></div></div>
                </div>
                <span className="w-16 shrink-0 text-center text-[10px] font-bold uppercase tracking-wider" style={{ color: DG_TROOP_COLOR[t] }}>{t}</span>
                <div className="flex flex-1 items-center gap-2">
                  <div className="h-2 w-full max-w-[110px] overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800"><div className="h-full rounded-full" style={{ width: (fb[t] / max * 100) + '%', background: DG_TROOP_COLOR[t] }}></div></div>
                  <span className={`text-[12px] tabular-nums ${fb[t] >= fa[t] && fb[t] > 0 ? 'font-bold text-zinc-900 dark:text-white' : 'text-zinc-400'}`}>{fb[t] || '—'}</span>
                </div>
              </div>
            ))}
          </div>
          <div className="mt-4 grid grid-cols-2 gap-3">
            {[a, b].map((d, i) => (
              <div key={i}>
                <div className="mb-1 text-[10.5px] font-bold uppercase tracking-wide text-zinc-400">{d.name} · Lv{d.tiers[d.tiers.length - 1].lv}</div>
                <div className="space-y-1">
                  {d.tiers[d.tiers.length - 1].buffs.map((bf, j) => (
                    <div key={j} className="flex items-start gap-1.5 text-[11.5px] leading-snug text-zinc-600 dark:text-zinc-300"><Icon name="bolt" size={11} className="mt-0.5 shrink-0 text-brand" />{bf}</div>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

/* ---------- bottom stats bar ---------- */
function DgStatsBar({ rows, assign }) {
  const stats = useMemoDG(() => {
    let power = 0, lvSum = 0, leg = 0, myth = 0, epic = 0;
    rows.forEach(({ d, focus }) => {
      const ft = Object.values(focus).reduce((s, v) => s + v, 0);
      power += 1.6 + ft / 120;
      lvSum += d.tiers[d.tiers.length - 1].lv;
      if (d.type === 'Elder') leg++; else if (ft > 45) myth++; else epic++;
    });
    const n = rows.length || 1;
    return { total: rows.length, power: power.toFixed(2), avgLv: Math.round(lvSum / n), leg, myth, epic, inBattle: Object.values(assign).filter(Boolean).length };
  }, [rows, assign]);

  const items = [
    { icon: 'flame', label: 'Total Dragons', value: stats.total, sub: 'in codex', color: '#FF6B00' },
    { icon: 'flame', label: 'Total Power', value: stats.power + 'B', sub: 'combined', color: '#FF6B00' },
    { icon: 'shield', label: 'Average Level', value: 'Lv ' + stats.avgLv, sub: 'max tier', color: '#22d3ee' },
    { icon: 'star', label: 'Legendary', value: stats.leg, sub: pct(stats.leg, stats.total), color: '#fbbf24' },
    { icon: 'star', label: 'Mythic', value: stats.myth, sub: pct(stats.myth, stats.total), color: '#a855f7' },
    { icon: 'star', label: 'Epic', value: stats.epic, sub: pct(stats.epic, stats.total), color: '#3b82f6' },
    { icon: 'scale', label: 'In Battle', value: stats.inBattle + ' / 4', sub: 'active marches', color: '#34d399' },
  ];
  function pct(v, t) { return t ? Math.round(v / t * 100) + '%' : '0%'; }

  return (
    <Card className="overflow-x-auto p-0">
      <div className="grid min-w-[680px] grid-cols-7 divide-x divide-zinc-100 dark:divide-zinc-800">
        {items.map(it => (
          <div key={it.label} className="flex items-center gap-2.5 px-3.5 py-3.5">
            <span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl" style={{ background: it.color + '1f', color: it.color }}><Icon name={it.icon} size={17} /></span>
            <div className="min-w-0">
              <div className="text-[9.5px] font-bold uppercase tracking-wider text-zinc-400">{it.label}</div>
              <div className="text-[17px] font-bold leading-tight text-zinc-900 dark:text-white">{it.value}</div>
              <div className="text-[10px] text-zinc-400">{it.sub}</div>
            </div>
          </div>
        ))}
      </div>
    </Card>
  );
}

/* ---------- main page ---------- */
function DragonCenterPage() {
  const all = (window.DRAGONCODEX && DRAGONCODEX.dragons) || [];
  const byName = useMemoDG(() => { const m = {}; all.forEach(d => m[d.name] = d); return m; }, [all]);
  const [assign, setAssign] = useStateDG(() => LS.get('vig2_dragon_assign', {}));
  const [sel, setSel] = useStateDG(null);
  const [q, setQ] = useStateDG('');
  const [type, setType] = useStateDG('All');
  const [best, setBest] = useStateDG('All');
  const [cmpMode, setCmpMode] = useStateDG(false);
  const [cmp, setCmp] = useStateDG([]);
  const [cmpOpen, setCmpOpen] = useStateDG(false);
  const setA = (t, name) => setAssign(a => { const n = { ...a }; if (name) n[t] = name; else delete n[t]; LS.set('vig2_dragon_assign', n); return n; });

  const rows = useMemoDG(() => all.map(d => ({ d, focus: dgFocus(d) })), [all]);
  const filtered = rows
    .filter(({ d }) => (type === 'All' || d.type === type) && (!q || d.name.toLowerCase().includes(q.toLowerCase())))
    .sort((a, b) => best === 'All' ? 0 : b.focus[best] - a.focus[best]);

  const assignedTo = name => DG_TROOPS.filter(t => assign[t] === name);
  const cardClick = d => {
    if (!cmpMode) { setSel(d); return; }
    setCmp(prev => {
      if (prev.find(x => x.name === d.name)) return prev.filter(x => x.name !== d.name);
      const next = [...prev, d].slice(-2);
      if (next.length === 2) setCmpOpen(true);
      return next;
    });
  };

  return (
    <div className="space-y-4">
      <style>{DG_CSS}</style>
      <DgSlots assign={assign} byName={byName} onPick={setSel} onClear={t => setA(t, null)} />

      <DgRecommend rows={rows} assign={assign} byName={byName} onAssign={(t, n) => setA(t, n)} onPick={setSel} />

      {/* filters — single clean row */}
      <div className="flex flex-wrap items-center gap-2">
        <Segmented options={['All', 'Standard', 'Elder']} value={type} onChange={setType} />
        <div className="flex items-center gap-1">
          {['All', ...DG_TROOPS].map(t => (
            <button key={t} onClick={() => setBest(t)} title={t === 'All' ? 'All troop types' : 'Best for ' + t} className={`flex items-center gap-1.5 rounded-lg border px-2.5 py-1.5 text-[12px] font-semibold transition-colors ${best === t ? 'text-white' : 'border-zinc-200 text-zinc-500 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-800'}`}
              style={best === t ? { background: t === 'All' ? '#FF6B00' : DG_TROOP_COLOR[t], borderColor: t === 'All' ? '#FF6B00' : DG_TROOP_COLOR[t] } : (t !== 'All' ? { borderColor: 'transparent' } : null)}>
              {t !== 'All' && <img src={DG_TROOP_IMG[t]} alt="" className="h-3.5 w-3.5" />}{t}
            </button>
          ))}
        </div>
        <button onClick={() => { setCmpMode(m => !m); setCmp([]); }} className={`inline-flex items-center gap-1.5 rounded-lg border px-2.5 py-1.5 text-[12px] font-semibold transition-colors ${cmpMode ? 'border-brand bg-brand text-white' : 'border-zinc-200 text-zinc-500 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-800'}`}><Icon name="scale" size={14} />{cmpMode ? `Pick 2 (${cmp.length}/2)` : 'Compare'}</button>
        <div className="relative ml-auto">
          <Icon name="search" size={14} className="absolute left-2.5 top-1/2 -translate-y-1/2 text-zinc-400" />
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search…" className="h-9 w-36 rounded-lg border border-zinc-200 bg-white pl-8 pr-2.5 text-[12.5px] outline-none focus:border-brand dark:border-zinc-700 dark:bg-zinc-900 sm:w-44" />
        </div>
      </div>

      {/* gallery */}
      <div className="grid grid-cols-2 gap-3 sm:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8">
        {filtered.map(({ d, focus }, i) => {
          const tags = assignedTo(d.name);
          const focusTotal = Object.values(focus).reduce((s, v) => s + v, 0);
          const bestT = DG_TROOPS.filter(t => focus[t] > 0).sort((a, b) => focus[b] - focus[a])[0];
          const stripe = bestT ? DG_TROOP_COLOR[bestT] : '#52525b';
          const inCmp = cmpMode && cmp.find(x => x.name === d.name);
          const lv = d.tiers[d.tiers.length - 1].lv;
          const powerB = (1.6 + focusTotal / 120).toFixed(2);
          const powerPct = Math.min(100, 40 + focusTotal / 1.6);
          const stars = d.type === 'Elder' ? 5 : focusTotal > 45 ? 5 : 4;
          return (
            <div key={d.name} className={`dg-card ${tags.length ? 'dg-assigned-ring' : ''} ${inCmp ? 'dg-assigned-ring' : ''}`} style={{ animationDelay: (i * 0.04) + 's', border: `1px solid ${stripe}66`, outline: inCmp ? '2px solid #FF6B00' : 'none' }} onClick={() => cardClick(d)}>
              <div className="dg-stripe" style={{ background: stripe }}></div>
              <div className="dg-halo"></div>
              <div className="dg-shine"></div>
              {/* full-bleed art */}
              <div className="dg-artwrap">
                <img src={dgImg(d.name)} alt={d.name} className="dg-art" loading="lazy" />
                <div className="dg-scrim"></div>
                {/* top badges */}
                <div className="absolute inset-x-0 top-0 z-10 flex items-start justify-between p-2.5">
                  {bestT ? (
                    <span className="flex items-center gap-1 rounded-md px-2 py-1 text-[9.5px] font-bold uppercase tracking-wider text-white" style={{ background: stripe + 'e6', boxShadow: `0 2px 10px -2px ${stripe}` }}>
                      <img src={DG_TROOP_IMG[bestT]} alt="" className="h-3 w-3" />{bestT}
                    </span>
                  ) : <span className="rounded-md bg-zinc-600/80 px-2 py-1 text-[9.5px] font-bold uppercase tracking-wider text-zinc-100">Utility</span>}
                  {inCmp ? <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-[11px] font-bold text-white">{cmp.findIndex(x => x.name === d.name) + 1}</span>
                    : cmpMode ? <span className="flex h-6 w-6 items-center justify-center rounded-full bg-white/15 text-[12px] font-bold text-white backdrop-blur">+</span>
                    : tags.length > 0 ? <span className="flex items-center gap-0.5 rounded-md bg-brand px-1.5 py-1 text-[8.5px] font-bold uppercase tracking-wider text-white"><Icon name="check" size={9} stroke={3} />{tags[0]}</span> : null}
                </div>
                {/* level hexagon */}
                <div className="absolute bottom-2 right-2.5 z-20 dg-hex" style={{ background: 'rgba(10,11,14,.82)', border: `1px solid ${stripe}` }}>
                  <span className="text-[12px] tabular-nums" style={{ color: stripe }}>{lv}</span>
                </div>
                {/* name + stars over art */}
                <div className="absolute inset-x-0 bottom-0 z-10 p-3 pr-12">
                  <div className="truncate text-[15px] font-bold leading-tight tracking-wide text-white" style={{ textShadow: '0 2px 8px rgba(0,0,0,.7)' }}>{d.name}</div>
                  <div className="mt-1 flex items-center gap-0.5">
                    {[0, 1, 2, 3, 4].map(s => <Icon key={s} name="star" size={11} className={s < stars ? 'text-amber-400' : 'text-zinc-600'} />)}
                    {d.type === 'Elder' && <span className="ml-1.5 rounded bg-amber-400/20 px-1.5 text-[8.5px] font-bold uppercase tracking-wider text-amber-300">Elder</span>}
                  </div>
                </div>
              </div>
              {/* power footer */}
              <div className="relative flex items-center gap-2 px-3 py-2.5" style={{ background: 'rgba(10,11,14,.6)' }}>
                <Icon name="flame" size={13} style={{ color: stripe }} />
                <span className="text-[12.5px] font-bold tabular-nums text-white">{powerB}B</span>
                <div className="dg-powerbar ml-auto w-1/2"><div className="h-full rounded-full" style={{ width: powerPct + '%', background: `linear-gradient(90deg, ${stripe}, ${stripe}aa)` }}></div></div>
              </div>
            </div>
          );
        })}
      </div>
      {!filtered.length && <Card className="p-8 text-center text-[13px] text-zinc-400">No dragons match.</Card>}

      <DgStatsBar rows={rows} assign={assign} />

      {sel && <DgDrawer d={sel} assign={assign} onAssign={(t, n) => setA(t, n)} onClose={() => setSel(null)} />}
      {cmpOpen && cmp.length === 2 && <DgCompare pair={cmp} onClose={() => { setCmpOpen(false); setCmp([]); setCmpMode(false); }} />}
      <p className="px-1 text-[11.5px] text-zinc-400">Tap any dragon for full intel — buffs by level, talents, refines and who should run it. Assignments are saved and shown on the march slots above.</p>
    </div>
  );
}
window.DragonCenterPage = DragonCenterPage;
