🎮ArcadeLab

指挥官 · Commander

by SwiftGalaxy49
4684 lines366.2 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>指挥官 · Commander</title>
<style>
  :root{
    --cw: min(66px, 12vw, 7.2vh);
    --ch: calc(var(--cw) * 1.38);
    --panel: #1c2130;
    --line: #2a3350;
    --accent: #4a7cff;
    --gold: #ffd75e;
    --text: #e6ebf5;
    --dim: #7c86a6;
    --red: #ff6b6b;
  }
  *{ box-sizing: border-box; }
  html, body{ height: 100%; margin: 0; }
  body{
    background: radial-gradient(ellipse at 50% -10%, #1e2942 0%, #0e1220 62%);
    color: var(--text);
    font-family: system-ui, "Microsoft YaHei", sans-serif;
    overflow: hidden;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
  }
  #app{ height: 100vh; height: 100dvh; display: flex; flex-direction: column; }
  .topbar{ flex: 0 0 auto; height: 42px; display: flex; align-items: center; justify-content: space-between; padding: 0 12px; border-bottom: 1px solid var(--line); background: rgba(20,24,36,.72); }
  .brand{ font-weight: 700; letter-spacing: 3px; font-size: 15px; }
  .brand small{ color: var(--dim); font-weight: 400; font-size: 9px; letter-spacing: 2px; margin-left: 6px; }
  .top-actions{ display: flex; align-items: center; gap: 8px; }
  .board{ flex: 1 1 auto; min-height: 0; width: 100%; max-width: 720px; margin: 0 auto; display: flex; flex-direction: column; gap: 4px; padding: 6px 8px 8px; }
  .hand-row{ flex: 0 0 auto; display: flex; justify-content: center; align-items: center; height: calc(var(--ch) + 4px); }
  .hand-row .card + .card{ margin-left: calc(var(--cw) * -0.22); }
  .battlefield{ flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
  .lane{ flex: 1 1 0; min-height: 0; display: flex; align-items: center; justify-content: center; gap: 4px; border-radius: 10px; padding: 4px; }
  .lane-enemy{ background: rgba(255,107,107,.05); }
  .lane-contested{ background: rgba(255,215,94,.05); }
  .lane-player{ background: rgba(74,124,255,.07); }
  .slot{ flex: 0 0 auto; width: var(--cw); height: var(--ch); border-radius: 9px; border: 1px dashed rgba(74,124,255,.18); display: grid; place-items: center; transition: border-color .15s, background .15s, box-shadow .15s; }
  .slot.empty.valid-target{ border-color: var(--accent); background: rgba(74,124,255,.12); border-style: solid; cursor: pointer; box-shadow: 0 0 10px rgba(74,124,255,.28) inset; }
  .slot.empty.valid-target:hover{ background: rgba(74,124,255,.22); }
  .slot.empty.valid-move{ border-color: var(--gold); background: rgba(255,215,94,.12); border-style: solid; cursor: pointer; box-shadow: 0 0 10px rgba(255,215,94,.28) inset; }
  .slot.empty.valid-move:hover{ background: rgba(255,215,94,.22); }
  .hq-slot{ flex: 0 0 auto; width: var(--cw); height: var(--ch); border-radius: 9px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; background: linear-gradient(180deg, #232b42, #1a2032); border: 1px solid var(--line); color: #c9d2e8; transition: border-color .15s, box-shadow .15s, background .15s; }
  .hq-slot .hq-label{ font-size: calc(var(--cw) * 0.14); letter-spacing: 1px; color: var(--dim); }
  .hq-slot .hq-hp{ font-size: calc(var(--cw) * 0.26); font-weight: 800; font-variant-numeric: tabular-nums; color: var(--gold); line-height: 1; }
  .hq-slot.enemy .hq-hp{ color: var(--red); }
  .hq-slot.valid-target{ cursor: pointer; border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold), 0 0 12px rgba(255,215,94,.4); }
  .card{ position: relative; width: var(--cw); height: var(--ch); border-radius: 9px; overflow: hidden; display: flex; flex-direction: column; border: 2px solid #f0f2f8; box-shadow: 0 3px 9px rgba(0,0,0,.5); transition: transform .12s ease, box-shadow .12s ease, opacity .2s, border-color .15s; }
  .card.r-common{ background: linear-gradient(180deg, #232838 0%, #12151f 100%); }
  .card.r-rare{ background: linear-gradient(180deg, #1c3a5c 0%, #0e1d30 100%); }
  .card.r-epic{ background: linear-gradient(180deg, #38205c 0%, #1c0e30 100%); }
  .card.r-legendary{ background: linear-gradient(180deg, #5c4a1c 0%, #30260e 100%); }
  .card.r-legendary .name{ color: #ffe6a3; }
  .card.hq{ background: #000 !important; border-color: #fff !important; }
  .card.hq .name{ color: #fff; padding: 4px 3px 0; }
  .card.hq .stats{ justify-content: center; }
  .card.hq .hp{ color: #fff; font-size: calc(var(--cw) * 0.22); }
  .card.hq .nation-badge{ color: #fff; background: rgba(0,0,0,.8); border-color: rgba(255,255,255,.55); }
  .card .cost-badge{ position: absolute; top: 3px; left: 3px; min-width: calc(var(--cw) * 0.38); padding: 1px 5px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; background: var(--accent); color: #fff; font-size: calc(var(--cw) * 0.135); font-weight: 700; letter-spacing: .2px; line-height: 1.35; box-shadow: 0 1px 4px rgba(0,0,0,.4); z-index: 2; font-variant-numeric: tabular-nums; white-space: nowrap; }
  .card .nation-badge{ position: absolute; top: 3px; right: 3px; width: calc(var(--cw) * 0.23); height: calc(var(--cw) * 0.23); border-radius: 50%; display: grid; place-items: center; background: rgba(0,0,0,.55); color: #e6ebf5; font-size: calc(var(--cw) * 0.135); font-weight: 700; line-height: 1; z-index: 2; border: 1px solid rgba(255,255,255,.28); }
  .card .name{ flex: 1 1 auto; display: grid; place-items: center; text-align: center; padding: 12px 3px 0; font-size: calc(var(--cw) * 0.145); font-weight: 700; color: #e8eefc; line-height: 1.15; word-break: break-all; overflow: hidden; }
  .card .stats{ display: flex; justify-content: space-between; padding: 2px 6px 3px; font-size: calc(var(--cw) * 0.18); font-weight: 700; font-variant-numeric: tabular-nums; }
  .card .atk{ color: var(--gold); }
  .card .hp{ color: #ff8a8a; }
  .card .kw-row{ display:flex; justify-content:center; gap:2px; padding:0 2px 1px; flex-wrap:nowrap; overflow:hidden; }
  .card .kw-row:empty{ display:none; }
  .card .kw{ font-style:normal; font-size:calc(var(--cw)*0.115); line-height:1.05; padding:0 3px; border-radius:3px; font-weight:700; color:#fff; }
  .kw-rush{ background:#c9761f; }
  .kw-double{ background:#c0392b; }
  .kw-mobile{ background:#2c6fbf; }
  .kw-stealth{ background:#6b3fa0; }
  .kw-firststrike{ background:#1f8a8a; }
  .kw-guard{ background:#2e8b57; }
  .card.command{ background: linear-gradient(180deg, #1c3350 0%, #0f1a28 100%) !important; }
  .card.command .cost-badge{ background: #3f8fd8; }
  .card.counter{ background: linear-gradient(180deg, #1e3d33 0%, #0d1c17 100%) !important; border-color: #6ee7a8; }
  .card.counter .cost-badge{ background: #2fae74; }
  .card.counter .name{ color: #b3ffd5; }
  .card.back{ display: grid; place-items: center; background: repeating-linear-gradient(45deg, #171d2c 0 6px, #1e2740 6px 12px) !important; border-color: #333f63 !important; color: #4d5980; font-size: calc(var(--cw) * 0.16); letter-spacing: 2px; font-weight: 700; }
  .card.hand{ cursor: pointer; }
  .card.hand:hover{ transform: translateY(-12px); box-shadow: 0 10px 18px rgba(0,0,0,.6); }
  .card.hand.unaffordable{ opacity: .42; }
  .card.hand.unaffordable:hover{ transform: translateY(-4px); }
  .card.unit.exhausted{ opacity: .5; filter: grayscale(.45); }
  .card.unit.can-act{ cursor: pointer; }
  .card.unit.can-act:hover{ transform: translateY(-4px); }
  .card.owned-enemy::before{ content: ''; position: absolute; inset: 0; border-radius: 7px; border: 1px solid rgba(255,107,107,.45); pointer-events: none; }
  .card.selected{ border-color: var(--gold) !important; box-shadow: 0 0 0 2px var(--gold), 0 8px 16px rgba(255,215,94,.35) !important; transform: translateY(-6px); }
  .card.targetable{ cursor: pointer; box-shadow: 0 0 0 2px var(--red), 0 0 12px rgba(255,107,107,.5) !important; }
  .btn{ border: 0; border-radius: 9px; cursor: pointer; padding: 8px 16px; font-size: 13px; font-weight: 600; color: #fff; background: var(--accent); font-family: inherit; transition: filter .15s, transform .08s; }
  .btn:hover{ filter: brightness(1.1); }
  .btn:active{ transform: scale(.97); }
  .btn:disabled{ opacity: .35; cursor: not-allowed; filter: none; transform: none; }
  .btn.ghost{ background: transparent; border: 1px solid var(--line); color: #9aa4bf; font-weight: 400; }
  .topbar .btn{ padding: 5px 11px; font-size: 12px; }
  .text-btn{ padding: 5px 12px; border-radius: 9px; background: rgba(28,33,48,.9); border: 1px solid var(--line); color: var(--text); font-size: 12px; font-family: inherit; cursor: pointer; transition: border-color .16s, background .16s, transform .1s; }
  .text-btn:hover{ border-color: #3a5aa8; background: #222b42; }
  .text-btn:active{ transform: scale(.97); }
  .info-bar{ flex: 0 0 auto; display: flex; align-items: center; gap: 10px; padding: 6px 10px; background: rgba(20,24,36,.6); border-top: 1px solid var(--line); font-size: 12px; }
  .info-side{ display: flex; align-items: center; gap: 8px; flex: 1 1 0; }
  .info-side.right{ justify-content: flex-end; }
  .info-hp{ color: #c9d2e8; font-variant-numeric: tabular-nums; }
  .info-kredits{ font-weight: 700; color: #7fb0ff; background: rgba(74,124,255,.13); border: 1px solid #2f4890; padding: 2px 8px; border-radius: 99px; font-variant-numeric: tabular-nums; }
  .info-counter{ font-weight: 700; color: #6ee7a8; background: rgba(110,231,168,.13); border: 1px solid #2d6b4c; padding: 2px 8px; border-radius: 99px; font-size: 11px; }
  .turn-info{ flex: 0 0 auto; font-size: 12px; color: var(--dim); letter-spacing: .5px; text-align: center; min-width: 130px; }
  .diff-tag{ flex: 0 0 auto; font-size: 10px; font-weight: 700; letter-spacing: 1px; padding: 2px 8px; border-radius: 99px; border: 1px solid var(--line); color: var(--dim); }
  .diff-tag.easy{ color: #6ee7a8; border-color: #2d6b4c; background: rgba(110,231,168,.08); }
  .diff-tag.normal{ color: #7fb0ff; border-color: #2f4890; background: rgba(74,124,255,.08); }
  .diff-tag.hard{ color: #ffb45e; border-color: #8a5a2e; background: rgba(255,180,94,.08); }
  .coin-badge{ display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 99px; background: linear-gradient(180deg, rgba(255,215,94,.16), rgba(255,183,74,.06)); border: 1px solid rgba(255,215,94,.38); color: var(--gold); font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
  .coin-badge.small{ padding: 3px 9px; font-size: 11px; }
  .toast{ position: fixed; left: 50%; bottom: 60px; transform: translate(-50%, 12px); background: rgba(28,33,48,.96); border: 1px solid var(--line); color: #cfe0ff; font-size: 12px; padding: 8px 16px; border-radius: 99px; opacity: 0; pointer-events: none; transition: all .22s ease; z-index: 90; white-space: nowrap; }
  .toast.show{ opacity: 1; transform: translate(-50%, 0); }
  .modal{ position: fixed; inset: 0; z-index: 50; display: none; place-items: center; padding: 16px; background: rgba(6,9,16,.78); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
  .modal.show{ display: grid; }
  .modal-card{ width: min(400px, 100%); max-height: calc(100vh - 32px); overflow: auto; background: var(--panel); border: 1px solid var(--line); border-radius: 16px; padding: 18px; box-shadow: 0 20px 50px rgba(0,0,0,.6); }
  .modal-head{ display: flex; align-items: center; justify-content: space-between; }
  .modal-head h2{ margin: 0; font-size: 15px; letter-spacing: 1px; }
  .btn-x{ background: transparent; border: 0; color: var(--dim); font-size: 16px; cursor: pointer; padding: 2px 6px; }
  .btn-x:hover{ color: var(--text); }
  .hint{ font-size: 11px; line-height: 1.7; color: var(--dim); margin: 10px 0 12px; }
  .modal-card textarea{ width: 100%; height: 74px; box-sizing: border-box; padding: 9px; border-radius: 9px; resize: none; border: 1px solid var(--line); background: #10131d; color: #7c86a6; font-size: 11px; font-family: ui-monospace, monospace; outline: none; }
  .modal-card textarea:focus, .modal-card input:focus{ border-color: #3a5aa8; }
  .modal-card input{ width: 100%; box-sizing: border-box; margin-top: 8px; padding: 9px 11px; border-radius: 9px; border: 1px solid var(--line); background: #10131d; color: var(--text); font-size: 13px; font-family: inherit; outline: none; }
  .modal-card .btn{ width: 100%; margin-top: 8px; }
  .save-status{ min-height: 16px; margin-top: 10px; font-size: 12px; text-align: center; color: #6ee7a8; }
  .credits-list{ display: flex; flex-direction: column; gap: 10px; padding: 6px 0; }
  .credits-item{ display: flex; align-items: center; gap: 12px; padding: 14px 14px; border-radius: 12px; background: rgba(28,33,48,.9); border: 1px solid var(--line); font-size: 14px; color: var(--text); font-weight: 500; }
  .credits-item .num{ flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center; border-radius: 50%; background: rgba(74,124,255,.16); border: 1px solid #2f4890; color: #90c0ff; font-size: 13px; font-weight: 700; }
  .cd-layout{ display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 4px 0; }
  .cd-preview .card{ --cw: 120px; pointer-events: none; }
  .cd-info{ width: 100%; display: flex; flex-direction: column; gap: 8px; }
  .cd-name{ text-align: center; font-size: 18px; font-weight: 700; letter-spacing: 2px; margin: 0; }
  .cd-badges{ display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; }
  .cd-rarity{ font-size: 11px; font-weight: 700; letter-spacing: 1px; padding: 3px 10px; border-radius: 99px; background: #2a3350; color: #9aa4bf; border: 1px solid #38446a; }
  .cd-rarity.r-rare{ background: rgba(74,158,255,.16); color: #90c0ff; border-color: #3a72b8; }
  .cd-rarity.r-epic{ background: rgba(160,107,255,.16); color: #c6a1ff; border-color: #6b4fb8; }
  .cd-rarity.r-legendary{ background: rgba(255,183,74,.16); color: #ffd75e; border-color: #a8823a; }
  .cd-cost-badge{ font-size: 11px; font-weight: 700; letter-spacing: 1px; padding: 3px 10px; border-radius: 99px; background: rgba(74,124,255,.15); color: #7fb0ff; border: 1px solid #2f4890; }
  .cd-utype{ font-size: 11px; font-weight: 700; letter-spacing: 1px; padding: 3px 10px; border-radius: 99px; background: rgba(255,215,94,.15); color: #ffd75e; border: 1px solid #8a6a2e; }
  .cd-nation{ font-size: 11px; font-weight: 700; letter-spacing: 1px; padding: 3px 10px; border-radius: 99px; background: rgba(160,160,160,.15); color: #c0c0c0; border: 1px solid #555; }
  .cd-stat-row{ display: flex; gap: 10px; margin-top: 4px; }
  .cd-stat{ flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 10px 6px; border-radius: 11px; background: rgba(12,16,32,.6); border: 1px solid var(--line); }
  .cd-stat small{ font-size: 10px; color: var(--dim); letter-spacing: 1px; }
  .cd-stat b{ font-size: 20px; font-variant-numeric: tabular-nums; }
  .cd-stat.atk b{ color: var(--gold); }
  .cd-stat.hp b{ color: #ff8a8a; }
  .cd-desc{ margin: 4px 0 0; padding: 10px 12px; border-radius: 10px; background: rgba(12,16,32,.6); border: 1px solid var(--line); font-size: 12.5px; line-height: 1.7; color: #b9c3da; min-height: 42px; }
  .cd-keywords{ display:flex; flex-direction:column; gap:6px; margin-top:6px; }
  .cd-kw-item{ font-size:11.5px; line-height:1.6; padding:6px 10px; border-radius:8px; background:rgba(74,124,255,.1); border:1px solid #2f4890; color:#b9c3da; }
  .cd-kw-item b{ color:#9ad6ff; margin-right:6px; }
  .cd-story{ margin: 4px 0 0; padding: 10px 12px; border-radius: 10px; background: rgba(12,16,32,.6); border: 1px solid var(--line); font-size: 12.5px; line-height: 1.7; color: #b9c3da; min-height: 42px; }
  .cd-story-btn{ margin-top: 8px; width: 100%; }
  .overlay{ position: fixed; inset: 0; z-index: 55; display: none; place-items: center; background: rgba(6,9,16,.8); }
  .overlay.show{ display: grid; }
  .overlay-card{ text-align: center; padding: 30px 40px; background: var(--panel); border: 1px solid var(--line); border-radius: 18px; min-width: 240px; }
  .overlay-title{ font-size: 26px; font-weight: 700; letter-spacing: 6px; margin-bottom: 10px; }
  .overlay-title.win{ color: var(--gold); }
  .overlay-title.lose{ color: #ff7b7b; }
  .overlay-reward{ font-size: 13px; font-weight: 700; color: var(--gold); margin-bottom: 18px; letter-spacing: 1px; }
  .lobby{ position: fixed; inset: 0; z-index: 40; display: grid; place-items: center; padding: 20px; background: radial-gradient(ellipse at 50% 0%, #1e2942 0%, #0b0e18 65%); transition: opacity .28s ease, visibility .28s; }
  .lobby.hidden{ opacity: 0; visibility: hidden; pointer-events: none; }
  .lobby-top{ position: absolute; top: 14px; right: 14px; display: flex; align-items: center; gap: 8px; }
  .lobby-inner{ width: min(300px, 100%); display: flex; flex-direction: column; gap: 18px; }
  .lobby-logo{ text-align: center; }
  .lobby-title{ font-size: 34px; font-weight: 800; letter-spacing: 8px; text-indent: 8px; background: linear-gradient(180deg, #ffffff 0%, #8fb2ff 100%); -webkit-background-clip: text; background-clip: text; color: transparent; line-height: 1.1; }
  .lobby-sub{ margin-top: 6px; font-size: 9px; letter-spacing: 3px; color: var(--dim); }
  .lobby-menu{ display: flex; flex-direction: column; gap: 8px; }
  .lobby-row{ display: flex; gap: 8px; }
  .lobby-row .menu-btn{ flex: 1 1 0; min-width: 0; }
  .menu-btn{ display: flex; align-items: center; width: 100%; text-align: left; padding: 10px 13px; border-radius: 11px; cursor: pointer; font-family: inherit; background: rgba(28,33,48,.9); border: 1px solid var(--line); color: var(--text); transition: background .16s, border-color .16s, transform .1s; }
  .menu-btn:hover{ border-color: #3a5aa8; background: #222b42; transform: translateY(-1px); }
  .menu-btn:active{ transform: scale(.985); }
  .menu-btn:disabled{ opacity: .38; cursor: not-allowed; transform: none; border-color: var(--line); background: rgba(28,33,48,.9); }
  .menu-btn.primary{ background: linear-gradient(180deg, #3f6fe8, #3559c4); border-color: #4a7cff; }
  .menu-btn.primary:hover{ background: linear-gradient(180deg, #4b7cf5, #3a62d6); border-color: #6b93ff; }
  .mb-text{ display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .mb-text b{ font-size: 13px; font-weight: 600; letter-spacing: .5px; }
  .mb-text small{ font-size: 10px; color: #8d98b8; }
  .menu-btn.primary .mb-text small{ color: #c6d6ff; }
  .lobby-foot{ text-align: center; font-size: 10px; color: #4d5980; letter-spacing: 1px; }
  .shop-balance{ display: flex; align-items: baseline; justify-content: center; gap: 8px; margin: 12px 0 14px; padding: 11px; border-radius: 12px; background: linear-gradient(180deg, rgba(255,215,94,.10), rgba(255,183,74,.04)); border: 1px solid rgba(255,215,94,.28); color: var(--gold); font-size: 21px; font-weight: 800; font-variant-numeric: tabular-nums; }
  .shop-balance small{ font-size: 11px; font-weight: 400; color: #b39a52; letter-spacing: 1px; }
  .shop-list{ display: flex; flex-direction: column; gap: 11px; }
  .shop-pack{ display: flex; align-items: center; gap: 12px; padding: 13px 14px; border-radius: 13px; background: linear-gradient(180deg, #232b42 0%, #1a2032 100%); border: 1px solid var(--line); transition: border-color .16s, transform .1s; }
  .shop-pack:hover{ border-color: #3a5aa8; transform: translateY(-1px); }
  .shop-pack-body{ flex: 1 1 auto; min-width: 0; }
  .shop-pack-name{ font-size: 14px; font-weight: 700; letter-spacing: .5px; }
  .shop-pack.officer .shop-pack-name{ color: var(--gold); }
  .shop-pack.hq .shop-pack-name{ color: #c6a1ff; }
  .shop-pack.hq{ background: linear-gradient(180deg, #2a2240 0%, #1a1430 100%); }
  .shop-pack-desc{ font-size: 11px; color: var(--dim); margin-top: 4px; line-height: 1.5; }
  .shop-pack-owned{ font-size: 11px; color: #90c0ff; margin-top: 3px; font-variant-numeric: tabular-nums; }
  .shop-buy{ flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; padding: 9px 14px; border-radius: 10px; font-size: 13px; font-weight: 700; font-family: inherit; cursor: pointer; color: #fff; border: 0; background: linear-gradient(180deg, #3f6fe8, #3559c4); font-variant-numeric: tabular-nums; white-space: nowrap; transition: filter .15s, transform .08s; }
  .shop-buy:hover{ filter: brightness(1.12); }
  .shop-buy:active{ transform: scale(.96); }
  .shop-buy:disabled{ opacity: .35; cursor: not-allowed; filter: none; transform: none; }
  .battle-label{ font-size: 11px; color: var(--dim); letter-spacing: 1.5px; margin: 14px 0 8px; }
  .battle-label:first-of-type{ margin-top: 8px; }
  .diff-list{ display: flex; flex-direction: column; gap: 8px; }
  .diff-btn{ display: flex; align-items: center; gap: 12px; padding: 11px 14px; border-radius: 12px; background: rgba(28,33,48,.9); border: 1px solid var(--line); color: var(--text); font-family: inherit; cursor: pointer; text-align: left; transition: border-color .15s, background .15s, transform .1s; }
  .diff-btn:hover{ border-color: #3a5aa8; }
  .diff-btn.selected{ border-color: var(--accent); background: rgba(74,124,255,.13); box-shadow: 0 0 0 1px var(--accent); }
  .diff-btn .d-name{ font-size: 14px; font-weight: 700; letter-spacing: .5px; }
  .diff-btn .d-desc{ font-size: 11px; color: var(--dim); margin-top: 2px; line-height: 1.5; }
  .diff-btn .d-reward{ flex: 0 0 auto; font-size: 13px; font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; padding: 4px 10px; border-radius: 99px; background: rgba(255,215,94,.1); border: 1px solid rgba(255,215,94,.3); }
  .diff-btn.selected .d-reward{ background: rgba(255,215,94,.18); }
  .deck-pick-list{ display: flex; flex-direction: column; gap: 8px; }
  .deck-pick{ display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: 11px; background: rgba(28,33,48,.9); border: 1px solid var(--line); color: var(--text); font-family: inherit; cursor: pointer; text-align: left; transition: border-color .15s, background .15s; }
  .deck-pick:hover{ border-color: #3a5aa8; }
  .deck-pick.selected{ border-color: var(--accent); background: rgba(74,124,255,.13); box-shadow: 0 0 0 1px var(--accent); }
  .deck-pick:disabled{ opacity: .35; cursor: not-allowed; }
  .deck-pick .dp-name{ flex: 1 1 auto; font-size: 13px; font-weight: 600; }
  .deck-pick .dp-count{ font-size: 11px; color: var(--dim); font-variant-numeric: tabular-nums; }
  .deck-pick.selected .dp-count{ color: #90c0ff; }
  .deck-pick.incomplete .dp-count{ color: #ff9b9b; }
  .pack-overlay{ position: fixed; inset: 0; z-index: 70; display: none; place-items: center; padding: 20px; background: radial-gradient(ellipse at 50% 40%, rgba(30,41,66,.97), rgba(6,9,16,.98)); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
  .pack-overlay.show{ display: grid; }
  .pack-inner{ display: flex; flex-direction: column; align-items: center; gap: 22px; max-width: 100%; }
  .pack-heading{ font-size: 15px; font-weight: 700; letter-spacing: 5px; color: var(--gold); text-align: center; }
  .pack-heading small{ display: block; margin-top: 6px; font-size: 10px; font-weight: 400; letter-spacing: 2px; color: var(--dim); }
  .pack-cards{ display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; max-width: min(620px, 96vw); }
  .pack-cards .card{ --cw: clamp(52px, 14vw, 76px); animation: cardIn .48s cubic-bezier(.18,.9,.32,1.35) backwards; cursor: pointer; }
  @keyframes cardIn{ from{ opacity: 0; transform: translateY(34px) scale(.55) rotate(-9deg); } to { opacity: 1; transform: translateY(0) scale(1) rotate(0deg); } }
  @keyframes flipIn{ from{ transform: rotateY(90deg) scale(.85); opacity: .4; } to { transform: rotateY(0) scale(1); opacity: 1; } }
  .codex-card{ width: min(620px, 100%); }
  .codex-tabs-row{ display: flex; align-items: center; gap: 8px; margin: 12px 0 10px; }
  .deck-tabs{ display: flex; gap: 6px; flex: 1 1 auto; flex-wrap: wrap; }
  .deck-tab{ padding: 5px 10px; border-radius: 7px; background: transparent; border: 1px solid var(--line); color: var(--dim); font-family: inherit; font-size: 11px; cursor: pointer; white-space: nowrap; transition: all .15s; }
  .deck-tab:hover{ color: var(--text); border-color: #3a5aa8; }
  .deck-tab.active{ background: rgba(74,124,255,.13); border-color: var(--accent); color: var(--text); }
  .deck-tab small{ opacity: .7; margin-left: 3px; font-variant-numeric: tabular-nums; }
  .nation-setup-hint{ font-size: 12px; color: var(--dim); text-align: center; margin: 8px 0 14px; letter-spacing: .5px; line-height: 1.6; }
  .nation-setup-label{ font-size: 12px; color: var(--text); letter-spacing: 1px; margin: 10px 0 8px; font-weight: 600; }
  .nation-setup-row{ display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
  .nation-setup-btn{ padding: 9px 16px; border-radius: 9px; background: rgba(28,33,48,.9); border: 1px solid var(--line); color: var(--text); font-family: inherit; font-size: 13px; cursor: pointer; transition: all .15s; }
  .nation-setup-btn:hover:not(:disabled){ border-color: var(--accent); color: #90c0ff; }
  .nation-setup-btn.selected{ background: rgba(74,124,255,.18); border-color: var(--accent); color: #c6d6ff; font-weight: 700; }
  .nation-setup-btn:disabled{ opacity: .3; cursor: not-allowed; }
  .nation-setup-actions{ display: flex; gap: 8px; margin-top: 16px; }
  .nation-setup-actions .btn{ flex: 1; width: auto; margin: 0; }
  .codex-toolbar{ display: flex; align-items: center; gap: 10px; margin: 0 0 12px; padding: 9px 12px; border-radius: 10px; background: rgba(12,16,32,.55); border: 1px solid var(--line); font-size: 12px; color: var(--dim); }
  .codex-toolbar .deck-num{ font-size: 15px; font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }
  .codex-toolbar .deck-num.warn{ color: #ff9b9b; }
  .codex-toolbar .spacer{ flex: 1 1 auto; }
  .active-deck-btn{ padding: 5px 12px; border-radius: 8px; background: rgba(74,124,255,.13); border: 1px solid var(--accent); color: #90c0ff; font-family: inherit; font-size: 11px; font-weight: 700; letter-spacing: 1px; cursor: pointer; transition: background .15s, transform .08s; }
  .active-deck-btn:hover{ background: rgba(74,124,255,.25); }
  .active-deck-btn:active{ transform: scale(.97); }
  .nation-pick{ display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 12px; padding: 9px 12px; border-radius: 10px; background: rgba(74,124,255,.07); border: 1px solid var(--line); animation: fadeSlide .2s ease; }
  @keyframes fadeSlide{ from{ opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
  .nation-pick .np-label{ font-size: 11px; color: var(--dim); letter-spacing: 1px; align-self: center; margin-right: 4px; }
  .nation-pick .np-btn{ padding: 5px 12px; border-radius: 8px; background: rgba(28,33,48,.9); border: 1px solid var(--line); color: var(--text); font-family: inherit; font-size: 12px; cursor: pointer; transition: all .15s; }
  .nation-pick .np-btn:hover{ border-color: var(--accent); color: #90c0ff; background: rgba(74,124,255,.13); }
  .codex-name-row{ display: flex; gap: 8px; align-items: center; margin: 0 0 12px; }
  .codex-name-row input{ flex: 1 1 auto; margin: 0; padding: 8px 11px; font-size: 12.5px; border-radius: 9px; border: 1px solid var(--line); background: #10131d; color: var(--text); font-family: inherit; outline: none; box-sizing: border-box; }
  .codex-name-row input:focus{ border-color: #3a5aa8; }
  .codex-name-row .btn{ width: auto; margin: 0; padding: 8px 14px; font-size: 12px; }
  .codex-legend{ display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 12px; font-size: 10.5px; color: var(--dim); }
  .codex-legend span{ display: inline-flex; align-items: center; gap: 5px; }
  .codex-legend i{ width: 11px; height: 11px; border-radius: 3px; border: 1.5px solid #f0f2f8; display: inline-block; }
  .codex-legend i.c-common{ background: #232838; }
  .codex-legend i.c-rare{ background: #1c3a5c; }
  .codex-legend i.c-epic{ background: #38205c; }
  .codex-legend i.c-legendary{ background: #5c4a1c; }
  .codex-grid{ display: grid; grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); gap: 10px; justify-items: center; max-height: calc(100vh - 460px); overflow-y: auto; padding-right: 4px; }
  .codex-grid::-webkit-scrollbar{ width: 6px; }
  .codex-grid::-webkit-scrollbar-thumb{ background: #2a3350; border-radius: 99px; }
  .codex-grid .card{ --cw: 78px; cursor: pointer; position: relative; margin: 0 auto; }
  .codex-grid .card.not-owned{ filter: grayscale(1); opacity: .32; }
  .codex-grid .card.locked{ filter: grayscale(1); opacity: .3; cursor: not-allowed; }
  .codex-grid .card:hover{ transform: translateY(-4px); box-shadow: 0 8px 16px rgba(0,0,0,.6); }
  .owned-badge, .deck-badge{ position: absolute; font-size: 9px; font-weight: 800; padding: 1px 5px; border-radius: 6px; z-index: 3; font-variant-numeric: tabular-nums; letter-spacing: .3px; pointer-events: none; }
  .owned-badge{ top: 3px; right: 3px; background: rgba(74,124,255,.85); color: #fff; }
  .deck-badge{ bottom: 3px; right: 3px; background: rgba(255,215,94,.92); color: #2a1f00; }
  .settings-label{ font-size: 12px; color: var(--dim); letter-spacing: 1px; margin: 14px 0 6px; }
  .volume-slider{ width: 100%; accent-color: var(--gold); margin: 0; display: block; }
  .settings-empty{ padding: 8px 10px 6px; text-align: center; color: var(--dim); font-size: 12.5px; line-height: 2; }
  .nation-filter{ display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; }
  .nation-tag{ font-size: 10px; padding: 3px 8px; border-radius: 99px; background: rgba(28,33,48,.9); border: 1px solid var(--line); color: var(--dim); cursor: pointer; font-family: inherit; transition: all .15s; }
  .nation-tag:hover{ color: var(--text); border-color: #3a5aa8; }
  .nation-tag.active{ background: rgba(74,124,255,.13); border-color: var(--accent); color: var(--text); }
  .nation-picker-menu{ display: flex; flex-direction: column; gap: 2px; padding: 6px; border-radius: 10px; background: var(--panel); border: 1px solid var(--line); box-shadow: 0 12px 30px rgba(0,0,0,.6); z-index: 200; min-width: 100px; }
  .nation-picker-btn{ padding: 6px 12px; border-radius: 7px; background: transparent; border: 0; color: var(--text); font-family: inherit; font-size: 12px; cursor: pointer; text-align: left; transition: background .15s; }
  .nation-picker-btn:hover{ background: rgba(74,124,255,.14); }
  .pack-room-list{ display: flex; flex-direction: column; gap: 8px; margin: 12px 0; }
  .pack-room-item{ display: flex; justify-content: space-between; align-items: center; padding: 11px 14px; border-radius: 10px; background: rgba(28,33,48,.6); border: 1px solid var(--line); cursor: pointer; font-size: 13px; transition: all .15s; }
  .pack-room-item:hover{ border-color: #3a5aa8; }
  .pack-room-item.selected{ border-color: var(--accent); background: rgba(74,124,255,.13); box-shadow: 0 0 0 1px var(--accent); }
  .pack-room-item.empty{ opacity: .4; }
  .pack-room-item.officer .pack-room-item-name{ color: var(--gold); }
  .pack-room-item-name{ font-weight: 600; letter-spacing: .5px; }
  .pack-room-item-count{ color: var(--gold); font-weight: 700; font-variant-numeric: tabular-nums; }
  .pack-room-empty-note{ font-size: 11px; color: var(--dim); text-align: center; line-height: 1.6; padding: 6px 4px; }
  .hq-owned-list{ display: grid; grid-template-columns: repeat(auto-fill, minmax(66px, 1fr)); gap: 8px; max-height: 220px; overflow-y: auto; padding: 4px; margin: 0 0 8px; }
  .hq-owned-list::-webkit-scrollbar{ width: 6px; }
  .hq-owned-list::-webkit-scrollbar-thumb{ background: #2a3350; border-radius: 99px; }
  .hq-owned-list .card{ --cw: 66px; cursor: pointer; position: relative; margin: 0 auto; }
  .hq-owned-list .card:hover{ transform: translateY(-4px); box-shadow: 0 8px 16px rgba(0,0,0,.6); }
  .hq-empty-note{ font-size: 11px; color: var(--dim); text-align: center; padding: 8px; line-height: 1.6; grid-column: 1 / -1; }
  .version-list{ display: flex; flex-direction: column; gap: 12px; max-height: calc(100vh - 200px); overflow-y: auto; padding-right: 4px; }
  .version-list::-webkit-scrollbar{ width: 6px; }
  .version-list::-webkit-scrollbar-thumb{ background: #2a3350; border-radius: 99px; }
  .version-item{ padding: 12px 14px; border-radius: 12px; background: rgba(28,33,48,.7); border: 1px solid var(--line); }
  .version-item .v-head{ display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
  .version-item .v-num{ font-size: 14px; font-weight: 800; color: var(--gold); }
  .version-item .v-title{ font-size: 12.5px; font-weight: 600; color: var(--text); }
  .version-item .v-date{ font-size: 10.5px; color: var(--dim); margin-left: auto; }
  .version-item ul{ margin: 0; padding-left: 18px; font-size: 12px; line-height: 1.75; color: #b9c3da; }
  .version-item li{ margin-bottom: 2px; }
</style>
</head>
<body>

<div class="lobby" id="lobby">
  <div class="lobby-top">
    <div class="coin-badge">金币 <span id="lobbyCoins">1000</span></div>
    <button class="text-btn" id="versionBtn">公告</button>
    <button class="text-btn" id="settingsBtn">设置</button>
  </div>

  <div class="lobby-inner">
    <div class="lobby-logo">
      <div class="lobby-title">指挥官</div>
      <div class="lobby-sub">C O M M A N D E R</div>
    </div>

    <div class="lobby-menu">
      <button class="menu-btn primary" id="startBtn">
        <span class="mb-text"><b>开始战役</b><small>选择难度与卡组</small></span>
      </button>
      <button class="menu-btn" id="loadBtn">
        <span class="mb-text"><b>读取存档</b><small>粘贴存档码还原进度</small></span>
      </button>
      <button class="menu-btn" id="shopBtn">
        <span class="mb-text"><b>商店</b><small>购买卡包与总部盲盒</small></span>
      </button>
      <div class="lobby-row">
        <button class="menu-btn" id="codexBtn">
          <span class="mb-text"><b>卡牌图鉴</b><small>查看 · 编辑卡组</small></span>
        </button>
        <button class="menu-btn" id="packBtn">
          <span class="mb-text"><b>拆包</b><small>开启卡包</small></span>
        </button>
      </div>
    </div>

    <div class="lobby-foot">v0.34</div>
  </div>
</div>

<div id="app">
  <header class="topbar">
    <div class="brand">指挥官 <small>COMMANDER</small></div>
    <div class="top-actions">
      <div class="coin-badge small">金币 <span id="gameCoins">1000</span></div>
      <button class="btn ghost" id="gameSettingsBtn">设置</button>
    </div>
  </header>

  <main class="board">
    <div class="hand-row" id="enemyHand"></div>
    <div class="battlefield">
      <div class="lane lane-enemy">
        <div class="slot" data-lane="enemyHome" data-idx="0"></div>
        <div class="slot" data-lane="enemyHome" data-idx="1"></div>
        <div class="hq-slot enemy" data-hq="enemy">
          <span class="hq-label">敌方总部</span>
          <span class="hq-hp" id="enemyHqHp">20</span>
        </div>
        <div class="slot" data-lane="enemyHome" data-idx="3"></div>
        <div class="slot" data-lane="enemyHome" data-idx="4"></div>
      </div>
      <div class="lane lane-contested">
        <div class="slot" data-lane="contested" data-idx="0"></div>
        <div class="slot" data-lane="contested" data-idx="1"></div>
        <div class="slot" data-lane="contested" data-idx="2"></div>
        <div class="slot" data-lane="contested" data-idx="3"></div>
        <div class="slot" data-lane="contested" data-idx="4"></div>
      </div>
      <div class="lane lane-player">
        <div class="slot" data-lane="playerHome" data-idx="0"></div>
        <div class="slot" data-lane="playerHome" data-idx="1"></div>
        <div class="hq-slot" data-hq="player">
          <span class="hq-label">我方总部</span>
          <span class="hq-hp" id="playerHqHp">20</span>
        </div>
        <div class="slot" data-lane="playerHome" data-idx="3"></div>
        <div class="slot" data-lane="playerHome" data-idx="4"></div>
      </div>
    </div>
    <div class="hand-row" id="playerHand"></div>
  </main>

  <div class="info-bar">
    <div class="info-side">
      <span class="diff-tag" id="diffTag">普通</span>
      <span class="info-hp" id="playerInfoHp">20 / 20</span>
      <span class="info-kredits" id="playerKredits">0 / 0</span>
      <span class="info-counter" id="playerCounter" style="display:none">应变</span>
      <span style="color:var(--dim);font-size:11px" id="playerMeta">手牌 0 · 牌库 0</span>
    </div>
    <div class="turn-info" id="turnInfo">第 1 回合 · 你的回合</div>
    <div class="info-side right">
      <span style="color:var(--dim);font-size:11px" id="enemyMeta">手牌 0 · 牌库 0</span>
      <button class="btn" id="endTurnBtn">结束回合</button>
    </div>
  </div>

  <div class="toast" id="toast"></div>

  <div class="modal" id="battleModal">
    <div class="modal-card">
      <div class="modal-head">
        <h2>开始战役</h2>
        <button class="btn-x" id="closeBattle">X</button>
      </div>
      <div class="battle-label">选择难度</div>
      <div class="diff-list" id="diffList"></div>
      <div class="battle-label">选择卡组</div>
      <div class="deck-pick-list" id="deckPickList"></div>
      <button class="btn" id="battleStartBtn" style="margin-top:18px" disabled>开 始 战 役</button>
    </div>
  </div>

  <div class="modal" id="modal">
    <div class="modal-card">
      <div class="modal-head">
        <h2>存档</h2>
        <button class="btn-x" id="closeModal">X</button>
      </div>
      <p class="hint">
        导出:设一个密码 → 生成存档码 → 复制保存(含金币与卡组)。<br>
        读入:把存档码粘贴到下面,输入同样的密码即可还原。
      </p>
      <textarea id="saveCode" placeholder="导出后这里是存档码;读档时粘贴到这里"></textarea>
      <input id="pwdInput" type="text" placeholder="密码(可留空)">
      <button class="btn" id="exportBtn">导出存档</button>
      <button class="btn" id="importBtn">读入存档</button>
      <button class="btn ghost" id="newGameBtn">重开新游戏</button>
      <div class="save-status" id="saveStatus"></div>
    </div>
  </div>

  <div class="modal" id="shopModal">
    <div class="modal-card">
      <div class="modal-head">
        <h2>商店</h2>
        <button class="btn-x" id="closeShop">X</button>
      </div>
      <div class="shop-balance">
        <span id="shopCoins">1000</span>
        <small>金币</small>
      </div>
      <div class="shop-list" id="shopList"></div>
      <div class="battle-label" style="margin-top:14px">已拥有的总部</div>
      <div class="hq-owned-list" id="hqOwnedList"></div>
      <p class="hint" style="text-align:center;margin-top:4px">购买的卡包会存入「拆包」,在大厅中开启</p>
    </div>
  </div>

  <div class="modal" id="packModal">
    <div class="modal-card">
      <div class="modal-head">
        <h2>拆包</h2>
        <button class="btn-x" id="closePackModal">X</button>
      </div>
      <p class="hint">选择卡包后点击开启按钮</p>
      <div class="pack-room-list" id="packRoomList"></div>
      <button class="btn" id="packOpenBtn" disabled>开 启</button>
      <div class="pack-room-empty-note" id="packRoomNote"></div>
    </div>
  </div>

  <div class="modal" id="codexModal">
    <div class="modal-card codex-card">
      <div class="modal-head">
        <h2>卡牌图鉴 · 卡组编辑</h2>
        <button class="btn-x" id="closeCodex">X</button>
      </div>

      <div class="codex-tabs-row">
        <div class="deck-tabs" id="deckTabs"></div>
      </div>

      <div id="nationSetup" style="display:none">
        <div class="nation-setup-hint">请先选择主国、盟国(可选)与总部<br>主国上限 40 张(无盟国)/ 30 张(有盟国)· 盟国上限 10 张 · 总牌数需满 40 张</div>
        <div class="nation-setup-label">选择主国</div>
        <div class="nation-setup-row" id="mainNationRow"></div>
        <div class="nation-setup-label">选择盟国(可选)</div>
        <div class="nation-setup-row" id="allyNationRow"></div>
        <div class="nation-setup-label">选择总部</div>
        <div class="nation-setup-row" id="hqRow"></div>
        <div class="nation-setup-actions">
          <button class="btn ghost" id="useActiveDeckBtn" disabled>使用现役卡组</button>
          <button class="btn" id="confirmNationsBtn" disabled>确 认</button>
        </div>
      </div>

      <div id="deckEditor" style="display:none">
        <div class="nation-filter" id="nationFilter"></div>

        <div class="codex-toolbar">
          <span>主国</span>
          <span class="deck-num"><span id="mainCount">0</span>/<span id="mainCapText">30</span></span>
          <span id="allyLabel">盟国</span>
          <span class="deck-num" id="allyNum"><span id="allyCount">0</span>/<span id="allyCapText">10</span></span>
          <span class="spacer"></span>
          <span>共</span>
          <span class="deck-num" id="totalNum"><span id="deckCount">0</span>/40</span>
          <button class="active-deck-btn" id="changeNationBtn">换国家</button>
        </div>

        <div class="codex-name-row">
          <input id="deckNameInput" type="text" maxlength="12" placeholder="输入卡组名称">
          <button class="btn ghost" id="clearDeckBtn">清空</button>
          <button class="btn" id="saveDeckBtn">保存</button>
        </div>

        <div class="codex-legend">
          <span><i class="c-common"></i>普通</span>
          <span><i class="c-rare"></i>稀有</span>
          <span><i class="c-epic"></i>特殊</span>
          <span><i class="c-legendary"></i>精锐</span>
          <span style="margin-left:auto">点击添加 · 长按看详情 · 灰色为不可加入</span>
        </div>

        <div class="codex-grid" id="codexGrid"></div>
      </div>
    </div>
  </div>

  <div class="modal" id="cardDetailModal">
    <div class="modal-card">
      <div class="modal-head">
        <h2>卡牌详情</h2>
        <button class="btn-x" id="closeCardDetail">X</button>
      </div>
      <div class="cd-layout">
        <div class="cd-preview" id="cdPreview"></div>
        <div class="cd-info">
          <h3 class="cd-name" id="cdName">卡牌</h3>
          <div class="cd-badges">
            <span class="cd-nation" id="cdNation" style="display:none"></span>
            <span class="cd-rarity" id="cdRarity">普通</span>
            <span class="cd-cost-badge" id="cdCostBadge">费用 1</span>
            <span class="cd-utype" id="cdUType" style="display:none">远程</span>
          </div>
          <div class="cd-stat-row">
            <div class="cd-stat atk"><small>攻击</small><b id="cdAtk">1</b></div>
            <div class="cd-stat hp"><small>生命</small><b id="cdHp">1</b></div>
          </div>
          <p class="cd-desc" id="cdDesc">描述</p>
          <div class="cd-keywords" id="cdKeywords" style="display:none"></div>
          <button class="btn cd-story-btn" id="cdStoryBtn">查看详情</button>
          <p class="cd-story" id="cdStory" style="display:none"></p>
        </div>
      </div>
    </div>
  </div>

  <div class="modal" id="settingsModal">
    <div class="modal-card">
      <div class="modal-head">
        <h2>设置</h2>
        <button class="btn-x" id="closeSettings">X</button>
      </div>
      <div class="settings-label">大厅音乐音量</div>
      <input type="range" id="hallVolume" class="volume-slider" min="0" max="1" step="0.01" value="0.6">
      <button class="btn" id="settingsHomeBtn" style="margin-top:16px">返回大厅</button>
      <button class="btn ghost" id="settingsSaveBtn">存档</button>
      <button class="btn ghost" id="creditsBtn">制作者名单</button>
    </div>
  </div>

  <div class="modal" id="creditsModal">
    <div class="modal-card">
      <div class="modal-head">
        <h2>制作者名单</h2>
        <button class="btn-x" id="closeCredits">X</button>
      </div>
      <div class="credits-list">
        <div class="credits-item"><span class="num">1</span><span>晚霞来令(比彭于晏还帅的)</span></div>
        <div class="credits-item"><span class="num">2</span><span>抑郁的某人</span></div>
        <div class="credits-item"><span class="num">3</span><span>人才</span></div>
      </div>
    </div>
  </div>

  <div class="modal" id="versionModal">
    <div class="modal-card">
      <div class="modal-head">
        <h2>更新公告</h2>
        <button class="btn-x" id="closeVersion">X</button>
      </div>
      <div class="version-list" id="versionList"></div>
    </div>
  </div>

  <div class="overlay" id="overlay">
    <div class="overlay-card">
      <div class="overlay-title" id="overlayTitle">胜利</div>
      <div class="overlay-reward" id="overlayReward">+50 金币</div>
      <button class="btn" id="overlayBtn">再来一局</button>
    </div>
  </div>

  <div class="pack-overlay" id="packOverlay">
    <div class="pack-inner">
      <div class="pack-heading" id="packTitle">
        普通包
        <small>点击卡牌翻开</small>
      </div>
      <div class="pack-cards" id="packCards"></div>
      <button class="btn" id="packOk" style="display:none">确 定</button>
    </div>
  </div>
</div>

<script>
/* ==================== 大厅音乐(循环) ==================== */
let hallCtx = null, hallMaster = null, hallTimer = null, hallNextLoopTime = 0, hallPlaying = false;
let hallActiveLoops = [];
let hallVolume = 0.6;
const HALL_BPM = 100, HALL_BEAT = 60 / HALL_BPM, HALL_BAR = 4 * HALL_BEAT, HALL_BARS = 16, HALL_LOOP = HALL_BARS * HALL_BAR, HALL_LOOKAHEAD = 1.0;
const hallMidi = n => 440 * Math.pow(2, (n - 69) / 12);
const HALL_CHORDS = [[50,53,57,62],[50,53,57,62],[46,50,53,58],[48,52,55,60],[50,53,57,62],[50,53,57,62],[43,46,50,55],[45,49,52,57],[50,53,57,62],[50,53,57,62],[46,50,53,58],[41,45,48,53],[43,46,50,55],[45,49,52,57],[50,53,57,62],[50,53,57,62]];
const HALL_BASSES = [38,38,34,36,38,38,31,33,38,38,34,29,31,33,38,38];
const HALL_MELODY = [[0,69,2,0.095],[2,74,2,0.095],[4,72,4,0.095],[8,70,2,0.095],[10,74,2,0.095],[12,72,4,0.095],[16,69,2,0.095],[18,65,2,0.095],[20,67,4,0.095],[24,70,2,0.095],[26,69,2,0.095],[28,69,4,0.095],[32,74,2,0.125],[34,77,2,0.125],[36,76,4,0.125],[40,74,2,0.125],[42,70,2,0.125],[44,72,4,0.125],[48,74,2,0.125],[50,67,2,0.125],[52,69,2,0.125],[54,73,2,0.125],[56,74,4,0.125],[60,74,4,0.125]];
function initHallAudio(){ if(hallCtx) return; hallCtx = new (window.AudioContext || window.webkitAudioContext)(); const comp = hallCtx.createDynamicsCompressor(); comp.threshold.value = -14; comp.knee.value = 20; comp.ratio.value = 4; comp.attack.value = 0.004; comp.release.value = 0.25; comp.connect(hallCtx.destination); hallMaster = hallCtx.createGain(); hallMaster.gain.value = 0.0001; hallMaster.connect(comp); }
function hallStrings(dest, freq, t, dur, vol){ const g = hallCtx.createGain(); const atk = Math.min(0.45, dur * 0.3), rel = Math.min(0.5, dur * 0.3); g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(vol, t + atk); g.gain.setValueAtTime(vol, t + dur - rel); g.gain.exponentialRampToValueAtTime(0.0001, t + dur); const lp = hallCtx.createBiquadFilter(); lp.type = 'lowpass'; lp.frequency.value = 1650; lp.Q.value = 0.6; lp.connect(dest); g.connect(lp); [-7,0,7].forEach(dt => { const o = hallCtx.createOscillator(); o.type = 'sawtooth'; o.frequency.value = freq; o.detune.value = dt; o.connect(g); o.start(t); o.stop(t + dur + 0.1); }); }
function hallBass(dest, freq, t, dur, vol){ const g = hallCtx.createGain(); g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(vol, t + 0.04); g.gain.setValueAtTime(vol, t + dur * 0.6); g.gain.exponentialRampToValueAtTime(0.0001, t + dur); const lp = hallCtx.createBiquadFilter(); lp.type = 'lowpass'; lp.frequency.value = 650; lp.connect(dest); g.connect(lp); const o1 = hallCtx.createOscillator(); o1.type = 'sine'; o1.frequency.value = freq; const o2 = hallCtx.createOscillator(); o2.type = 'sawtooth'; o2.frequency.value = freq; const g2 = hallCtx.createGain(); g2.gain.value = 0.32; o1.connect(g); o2.connect(g2).connect(g); o1.start(t); o1.stop(t + dur + 0.1); o2.start(t); o2.stop(t + dur + 0.1); }
function hallBrass(dest, freq, t, dur, vol){ const g = hallCtx.createGain(); g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(vol, t + 0.07); g.gain.setValueAtTime(vol, t + dur * 0.72); g.gain.exponentialRampToValueAtTime(0.0001, t + dur); const lp = hallCtx.createBiquadFilter(); lp.type = 'lowpass'; lp.frequency.setValueAtTime(520, t); lp.frequency.exponentialRampToValueAtTime(3100, t + 0.12); lp.frequency.exponentialRampToValueAtTime(1600, t + dur); lp.Q.value = 1.1; lp.connect(dest); g.connect(lp); const o1 = hallCtx.createOscillator(); o1.type = 'sawtooth'; o1.frequency.value = freq; const o2 = hallCtx.createOscillator(); o2.type = 'square'; o2.frequency.value = freq; const g2 = hallCtx.createGain(); g2.gain.value = 0.28; o1.connect(g); o2.connect(g2).connect(g); o1.start(t); o1.stop(t + dur + 0.1); o2.start(t); o2.stop(t + dur + 0.1); }
function hallTimpani(dest, freq, t, vol, dur){ dur = dur || 0.9; const g = hallCtx.createGain(); g.gain.setValueAtTime(vol, t); g.gain.exponentialRampToValueAtTime(0.0001, t + dur); g.connect(dest); const o = hallCtx.createOscillator(); o.type = 'sine'; o.frequency.setValueAtTime(freq * 1.7, t); o.frequency.exponentialRampToValueAtTime(freq, t + 0.08); o.connect(g); o.start(t); o.stop(t + dur + 0.1); const bl = Math.floor(hallCtx.sampleRate * 0.04); const buf = hallCtx.createBuffer(1, bl, hallCtx.sampleRate); const d = buf.getChannelData(0); for(let i=0;i<bl;i++) d[i] = (Math.random()*2-1) * Math.pow(1 - i/bl, 4); const n = hallCtx.createBufferSource(); n.buffer = buf; const nf = hallCtx.createBiquadFilter(); nf.type = 'bandpass'; nf.frequency.value = 180; const ng = hallCtx.createGain(); ng.gain.value = vol * 0.5; n.connect(nf).connect(ng).connect(dest); n.start(t); }
function hallSnare(dest, t, vol){ const bl = Math.floor(hallCtx.sampleRate * 0.15); const buf = hallCtx.createBuffer(1, bl, hallCtx.sampleRate); const d = buf.getChannelData(0); for(let i=0;i<bl;i++) d[i] = (Math.random()*2-1) * Math.pow(1 - i/bl, 3); const n = hallCtx.createBufferSource(); n.buffer = buf; const bp = hallCtx.createBiquadFilter(); bp.type = 'bandpass'; bp.frequency.value = 2000; bp.Q.value = 0.8; const g = hallCtx.createGain(); g.gain.value = vol; n.connect(bp).connect(g).connect(dest); n.start(t); const o = hallCtx.createOscillator(); o.type = 'sine'; o.frequency.setValueAtTime(200, t); o.frequency.exponentialRampToValueAtTime(100, t + 0.05); const og = hallCtx.createGain(); og.gain.setValueAtTime(vol * 0.5, t); og.gain.exponentialRampToValueAtTime(0.0001, t + 0.08); o.connect(og).connect(dest); o.start(t); o.stop(t + 0.1); }
function hallScheduleLoop(t0){ const lg = hallCtx.createGain(); lg.gain.value = 1; lg.connect(hallMaster); hallActiveLoops.push({ gain: lg, end: t0 + HALL_LOOP }); for(let bar = 0; bar < HALL_BARS; bar++){ const tb = t0 + bar * HALL_BAR; const chord = HALL_CHORDS[bar]; const bassMidi = HALL_BASSES[bar]; const isB = bar >= 8; chord.forEach((n, i) => { hallStrings(lg, hallMidi(n), tb + i * 0.03, HALL_BAR * 0.98, 0.055); }); for(let b = 0; b < 4; b++){ hallBass(lg, hallMidi(bassMidi), tb + b * HALL_BEAT, HALL_BEAT * 0.9, 0.15); } const sv = isB ? 1.15 : 0.8; hallSnare(lg, tb + 0.00 * HALL_BEAT, 0.10 * sv); hallSnare(lg, tb + 0.75 * HALL_BEAT, 0.05 * sv); hallSnare(lg, tb + 1.00 * HALL_BEAT, 0.08 * sv); hallSnare(lg, tb + 1.75 * HALL_BEAT, 0.05 * sv); hallSnare(lg, tb + 2.00 * HALL_BEAT, 0.10 * sv); hallSnare(lg, tb + 2.75 * HALL_BEAT, 0.05 * sv); hallSnare(lg, tb + 3.00 * HALL_BEAT, 0.08 * sv); hallSnare(lg, tb + 3.75 * HALL_BEAT, 0.05 * sv); const tv = isB ? 0.30 : 0.20; hallTimpani(lg, hallMidi(bassMidi), tb, tv); hallTimpani(lg, hallMidi(bassMidi), tb + 2 * HALL_BEAT, tv * 0.68); if(bar % 4 === 3){ hallTimpani(lg, hallMidi(bassMidi), tb + 3.5 * HALL_BEAT, tv * 0.55); hallTimpani(lg, hallMidi(bassMidi), tb + 3.75 * HALL_BEAT, tv * 0.45); } } HALL_MELODY.forEach(([beat, n, durBeats, vol]) => { const t = t0 + beat * HALL_BEAT; const d = durBeats * HALL_BEAT * 0.94; hallBrass(lg, hallMidi(n), t, d, vol); if(beat >= 32){ hallBrass(lg, hallMidi(n - 12), t, d, vol * 0.45); } }); hallActiveLoops = hallActiveLoops.filter(e => e.end > hallCtx.currentTime - 1); }
function startHallMusic(){ try { initHallAudio(); if(hallPlaying){ if(hallCtx.state === 'suspended') hallCtx.resume().catch(()=>{}); return; } const doStart = () => { if(hallPlaying) return; hallPlaying = true; const t = hallCtx.currentTime; hallMaster.gain.cancelScheduledValues(t); hallMaster.gain.setValueAtTime(0.0001, t); hallMaster.gain.linearRampToValueAtTime(hallVolume, t + 1.4); hallNextLoopTime = t + 0.15; hallScheduleLoop(hallNextLoopTime); hallNextLoopTime += HALL_LOOP; hallTimer = setInterval(() => { if(hallNextLoopTime < hallCtx.currentTime + HALL_LOOKAHEAD){ hallScheduleLoop(hallNextLoopTime); hallNextLoopTime += HALL_LOOP; } }, 250); }; if(hallCtx.state === 'suspended'){ hallCtx.resume().then(doStart).catch(()=>{}); } else { doStart(); } } catch(e){} }
function stopHallMusic(){ if(!hallPlaying || !hallCtx) return; hallPlaying = false; clearInterval(hallTimer); try { const t = hallCtx.currentTime; hallMaster.gain.cancelScheduledValues(t); hallMaster.gain.setValueAtTime(hallMaster.gain.value, t); hallMaster.gain.linearRampToValueAtTime(0.0001, t + 0.9); } catch(e){} setTimeout(() => { if(hallPlaying) return; hallActiveLoops.forEach(e => { try { e.gain.disconnect(); } catch(err){} }); hallActiveLoops = []; if(hallCtx) hallCtx.suspend(); }, 1100); }
function setHallVolume(v){ hallVolume = Math.max(0, Math.min(1, v)); if(hallMaster && hallPlaying){ try { const t = hallCtx.currentTime; hallMaster.gain.cancelScheduledValues(t); hallMaster.gain.setValueAtTime(hallVolume, t); } catch(e){} } }

/* ==================== 无法选择音效(得得得) ==================== */
let denyCtx = null, denyMaster = null, denyNoiseBuf = null;
function initDenyAudio(){ if(denyCtx) return; denyCtx = new (window.AudioContext || window.webkitAudioContext)(); const comp = denyCtx.createDynamicsCompressor(); comp.threshold.value = -13; comp.knee.value = 18; comp.ratio.value = 4; comp.attack.value = 0.002; comp.release.value = 0.18; comp.connect(denyCtx.destination); denyMaster = denyCtx.createGain(); denyMaster.gain.value = 0.9; denyMaster.connect(comp); const len = denyCtx.sampleRate; denyNoiseBuf = denyCtx.createBuffer(1, len, denyCtx.sampleRate); const d = denyNoiseBuf.getChannelData(0); for(let i = 0; i < len; i++) d[i] = Math.random() * 2 - 1; }
function denyKnock(t, vol, freq){ const out = denyCtx.createGain(); out.connect(denyMaster); const n = denyCtx.createBufferSource(); n.buffer = denyNoiseBuf; const bp = denyCtx.createBiquadFilter(); bp.type = 'bandpass'; bp.frequency.value = 1300; bp.Q.value = 1.1; const lp = denyCtx.createBiquadFilter(); lp.type = 'lowpass'; lp.frequency.value = 2600; const ng = denyCtx.createGain(); ng.gain.setValueAtTime(0.0001, t); ng.gain.exponentialRampToValueAtTime(vol, t + 0.002); ng.gain.exponentialRampToValueAtTime(0.0001, t + 0.075); n.connect(bp).connect(lp).connect(ng).connect(out); n.start(t); n.stop(t + 0.09); const o = denyCtx.createOscillator(); o.type = 'triangle'; o.frequency.setValueAtTime(freq, t); o.frequency.exponentialRampToValueAtTime(freq * 0.72, t + 0.06); const og = denyCtx.createGain(); og.gain.setValueAtTime(0.0001, t); og.gain.exponentialRampToValueAtTime(vol * 0.75, t + 0.002); og.gain.exponentialRampToValueAtTime(0.0001, t + 0.085); o.connect(og).connect(out); o.start(t); o.stop(t + 0.1); }
function playDenySound(){ try { initDenyAudio(); if(denyCtx.state === 'suspended') denyCtx.resume(); const t0 = denyCtx.currentTime + 0.01; denyKnock(t0 + 0.00, 0.85, 420); denyKnock(t0 + 0.13, 0.80, 420); denyKnock(t0 + 0.28, 0.68, 400); const n2 = denyCtx.createBufferSource(); n2.buffer = denyNoiseBuf; const hp = denyCtx.createBiquadFilter(); hp.type = 'highpass'; hp.frequency.value = 3000; const g2 = denyCtx.createGain(); g2.gain.setValueAtTime(0.0001, t0); g2.gain.exponentialRampToValueAtTime(0.035, t0 + 0.01); g2.gain.exponentialRampToValueAtTime(0.0001, t0 + 0.42); n2.connect(hp).connect(g2).connect(denyMaster); n2.start(t0); n2.stop(t0 + 0.45); } catch(e){} }

/* ==================== 拆包音效(滋——) ==================== */
let ctx = null, master = null, noiseBuf = null;
function initAudio(){ if(ctx) return; ctx = new (window.AudioContext || window.webkitAudioContext)(); const comp = ctx.createDynamicsCompressor(); comp.threshold.value = -12; comp.knee.value = 18; comp.ratio.value = 4; comp.attack.value = 0.003; comp.release.value = 0.2; comp.connect(ctx.destination); master = ctx.createGain(); master.gain.value = 0.85; master.connect(comp); const len = ctx.sampleRate * 2; noiseBuf = ctx.createBuffer(1, len, ctx.sampleRate); const d = noiseBuf.getChannelData(0); for(let i = 0; i < len; i++) d[i] = Math.random() * 2 - 1; }
function makeDrive(k){ const n = 512, curve = new Float32Array(n); for(let i = 0; i < n; i++){ const x = (i / (n - 1)) * 2 - 1; curve[i] = Math.tanh(k * x) / Math.tanh(k); } const ws = ctx.createWaveShaper(); ws.curve = curve; ws.oversample = '2x'; return ws; }
function playRipSound(){ initAudio(); if(ctx.state === 'suspended') ctx.resume(); const t0 = ctx.currentTime + 0.01; const DUR = 1.0; const out = ctx.createGain(); out.connect(master); const src = ctx.createBufferSource(); src.buffer = noiseBuf; src.loop = true; const bp = ctx.createBiquadFilter(); bp.type = 'bandpass'; bp.Q.value = 9; const f = bp.frequency; f.setValueAtTime(4200, t0); f.linearRampToValueAtTime(7800, t0 + 0.09); f.linearRampToValueAtTime(3200, t0 + 0.26); f.linearRampToValueAtTime(8500, t0 + 0.44); f.linearRampToValueAtTime(3600, t0 + 0.62); f.linearRampToValueAtTime(6400, t0 + 0.80); f.linearRampToValueAtTime(2400, t0 + 1.00); const g = ctx.createGain(); g.gain.setValueAtTime(0.0001, t0); g.gain.exponentialRampToValueAtTime(0.88, t0 + 0.02); g.gain.setValueAtTime(0.88, t0 + 0.12); g.gain.linearRampToValueAtTime(0.58, t0 + 0.46); g.gain.linearRampToValueAtTime(0.80, t0 + 0.74); g.gain.exponentialRampToValueAtTime(0.0001, t0 + 1.00); src.connect(bp).connect(g).connect(out); const osc = ctx.createOscillator(); osc.type = 'sawtooth'; osc.frequency.setValueAtTime(180, t0); osc.frequency.linearRampToValueAtTime(330, t0 + 0.5); osc.frequency.linearRampToValueAtTime(150, t0 + 1.0); const oscBP = ctx.createBiquadFilter(); oscBP.type = 'bandpass'; oscBP.frequency.value = 3000; oscBP.Q.value = 2.2; const og = ctx.createGain(); og.gain.setValueAtTime(0.0001, t0); og.gain.exponentialRampToValueAtTime(0.11, t0 + 0.03); og.gain.setValueAtTime(0.11, t0 + 0.60); og.gain.exponentialRampToValueAtTime(0.0001, t0 + 0.95); osc.connect(makeDrive(5)).connect(oscBP).connect(og).connect(out); osc.start(t0); osc.stop(t0 + DUR + 0.05); const src2 = ctx.createBufferSource(); src2.buffer = noiseBuf; src2.loop = true; const hp = ctx.createBiquadFilter(); hp.type = 'highpass'; hp.frequency.value = 6500; const g2 = ctx.createGain(); g2.gain.setValueAtTime(0.0001, t0); g2.gain.exponentialRampToValueAtTime(0.22, t0 + 0.03); g2.gain.linearRampToValueAtTime(0.10, t0 + 0.60); g2.gain.exponentialRampToValueAtTime(0.0001, t0 + 0.95); src2.connect(hp).connect(g2).connect(out); const COUNT = 55; for(let i = 0; i < COUNT; i++){ const dt = t0 + Math.random() * DUR * 0.90; const b = ctx.createBufferSource(); b.buffer = noiseBuf; const bbp = ctx.createBiquadFilter(); bbp.type = 'bandpass'; bbp.frequency.value = 4000 + Math.random() * 8000; bbp.Q.value = 6 + Math.random() * 8; const bg = ctx.createGain(); const v = 0.03 + Math.random() * 0.11; bg.gain.setValueAtTime(0.0001, dt); bg.gain.exponentialRampToValueAtTime(v, dt + 0.001); bg.gain.exponentialRampToValueAtTime(0.0001, dt + 0.008 + Math.random() * 0.02); b.connect(bbp).connect(bg).connect(out); b.start(dt, Math.random() * 1.5); b.stop(dt + 0.04); } const end = t0 + DUR + 0.1; src.start(t0); src.stop(end); src2.start(t0); src2.stop(end); }

/* ==================== 金币音效(叮——) ==================== */
let coinCtx = null, coinMaster = null;
function initCoinAudio(){ if(coinCtx) return; coinCtx = new (window.AudioContext || window.webkitAudioContext)(); const comp = coinCtx.createDynamicsCompressor(); comp.threshold.value = -14; comp.knee.value = 18; comp.ratio.value = 4; comp.attack.value = 0.002; comp.release.value = 0.2; comp.connect(coinCtx.destination); coinMaster = coinCtx.createGain(); coinMaster.gain.value = 0.9; coinMaster.connect(comp); }
function coinMetallic(freq, t, vol, dur, bright){ const g = coinCtx.createGain(); g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(vol, t + 0.004); g.gain.exponentialRampToValueAtTime(0.0001, t + dur); const lp = coinCtx.createBiquadFilter(); lp.type = 'lowpass'; lp.frequency.value = bright ? 9000 : 5000; g.connect(lp).connect(coinMaster); const partials = [[1.00,1.00,1.00],[2.00,0.42,0.72],[2.76,0.28,0.58],[5.40,0.14,0.42]]; partials.forEach(([ratio, amp, decay]) => { const o = coinCtx.createOscillator(); o.type = 'sine'; o.frequency.value = freq * ratio; o.frequency.linearRampToValueAtTime(freq * ratio * 0.985, t + dur * 0.7); const pg = coinCtx.createGain(); pg.gain.setValueAtTime(0.0001, t); pg.gain.exponentialRampToValueAtTime(vol * amp, t + 0.003); pg.gain.exponentialRampToValueAtTime(0.0001, t + dur * decay); o.connect(pg).connect(g); o.start(t); o.stop(t + dur + 0.05); }); }
function playCoinSound(){ initCoinAudio(); if(coinCtx.state === 'suspended') coinCtx.resume(); const t0 = coinCtx.currentTime + 0.01; coinMetallic(2500, t0, 0.55, 0.85, true); { const len = Math.floor(coinCtx.sampleRate * 0.03); const buf = coinCtx.createBuffer(1, len, coinCtx.sampleRate); const d = buf.getChannelData(0); for(let i = 0; i < len; i++) d[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / len, 5); const n = coinCtx.createBufferSource(); n.buffer = buf; const hp = coinCtx.createBiquadFilter(); hp.type = 'highpass'; hp.frequency.value = 4000; const ng = coinCtx.createGain(); ng.gain.setValueAtTime(0.18, t0); ng.gain.exponentialRampToValueAtTime(0.0001, t0 + 0.025); n.connect(hp).connect(ng).connect(coinMaster); n.start(t0); } coinMetallic(3100, t0 + 0.11, 0.22, 0.45, true); coinMetallic(2800, t0 + 0.24, 0.08, 0.28, false); }

/* ==================== 版本历史 ==================== */
const VERSIONS = [
  {
    version: 'v0.34',
    date: '2026',
    title: '反击机制与卡牌词条',
    items: [
      '新增反击机制:近战单位互相攻击时,目标存活会反击造成等量伤害',
      '远程单位(炮兵/轰炸机)攻击时不会遭受反击',
      '新增 6 种卡牌词条:急袭、连击、机动、隐匿、奇袭、护卫',
      '卡牌详情中显示词条名称与效果说明'
    ]
  },
  {
    version: 'v0.33',
    date: '2026',
    title: '盟国可选与总部选择',
    items: [
      '盟国改为可选:不选盟国时主国卡组上限提升至 40 张',
      '新增"选择总部"步骤:从拥有的主国/盟国总部中选择一个',
      '国家选择界面新增"使用现役卡组"按钮,一键生成 40 张默认卡组',
      '旧存档自动兼容,卡组数据会保留'
    ]
  },
  {
    version: 'v0.23',
    date: '2026',
    title: '总部牌与卡组构建重做',
    items: [
      '新增 25 张总部牌(5 国 × 5 张),所有总部统一为 20 点生命',
      '总部牌边框改为白色、底色改为黑色,与其他卡牌区分',
      '商店新增总部盲盒(500 金币),可随机开出总部牌',
      '卡组构建加入主国/盟国设定:主国上限 30 张、盟国上限 10 张、总数需满 40 张才能开战',
      '组卡前必须先选主国与盟国,未选择则无法添加卡片',
      '图鉴新增"全部"按钮:点击查看所有国家的卡,长按可单独选择国家',
      '非主国/盟国的卡显示为灰色,点击会提示无法加入',
      '对局设置只影响 AI 强度,简单/普通/困难逐级提升',
      '大厅新增公告按钮,可查看版本更新',
      '大厅底部仅显示版本号'
    ]
  }
];

/* ==================== 存档模块 ==================== */
const Save = (() => {
  const PREFIX = 'SAVE1.', MAGIC = 'GAME-SAVE-OK';
  const enc = new TextEncoder(), dec = new TextDecoder();
  function hashPassword(pwd) { let h = 2166136261 >>> 0; const s = 'x' + pwd + 'x'; for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 16777619) >>> 0; } return h >>> 0; }
  function makeRng(seed) { let s = (seed || 1) >>> 0; return () => { s = (Math.imul(s, 1664525) + 1013904223) >>> 0; return s; }; }
  function xorBytes(bytes, pwd) { const rng = makeRng(hashPassword(pwd)); const out = new Uint8Array(bytes.length); for (let i = 0; i < bytes.length; i++) out[i] = bytes[i] ^ (rng() & 0xff); return out; }
  function toBase64(b) { let s = ''; for (let i = 0; i < b.length; i++) s += String.fromCharCode(b[i]); return btoa(s); }
  function fromBase64(b64) { const s = atob(b64), b = new Uint8Array(s.length); for (let i = 0; i < s.length; i++) b[i] = s.charCodeAt(i); return b; }
  return { exportCode(state, password) { return PREFIX + toBase64(xorBytes(enc.encode(MAGIC + JSON.stringify(state)), password || '')); }, importCode(code, password) { code = (code || '').trim(); if (!code.startsWith(PREFIX)) return { error: '存档格式不正确' }; try { const json = dec.decode(xorBytes(fromBase64(code.slice(PREFIX.length)), password || '')); if (!json.startsWith(MAGIC)) return { error: '密码错误' }; return { data: JSON.parse(json.slice(MAGIC.length)) }; } catch (e) { return { error: '存档损坏或密码错误' }; } } };
})();

/* ==================== 稀有度 / 国家 ==================== */
const RARITY = { common: { name: '普通', cls: 'r-common' }, rare: { name: '稀有', cls: 'r-rare' }, epic: { name: '特殊', cls: 'r-epic' }, legendary: { name: '精锐', cls: 'r-legendary' } };
const RARITY_ORDER = ['common', 'rare', 'epic', 'legendary'];
const NATIONS = { usa: { name: '美国', abbr: '美' }, ussr: { name: '苏联', abbr: '苏' }, japan: { name: '日本', abbr: '日' }, uk: { name: '英国', abbr: '英' }, germany: { name: '德国', abbr: '德' } };
const NATION_ORDER = ['usa', 'ussr', 'japan', 'uk', 'germany'];

/* ==================== 词条系统 ==================== */
const KEYWORDS = {
  rush:        { id:'rush',        name:'急袭', short:'急', desc:'部署后可直接进攻或移动一次(进场即可行动)。' },
  double:      { id:'double',      name:'连击', short:'连', desc:'一回合内可连续进攻两次。' },
  mobile:      { id:'mobile',      name:'机动', short:'机', desc:'本回合攻击后仍可移动。' },
  stealth:     { id:'stealth',     name:'隐匿', short:'隐', desc:'部署当回合若未进攻也未移动,不会被敌方单位选为目标(仍可被作战令或应变指定)。' },
  firststrike: { id:'firststrike', name:'奇袭', short:'奇', desc:'第一次攻击时不遭受反击伤害。' },
  guard:       { id:'guard',       name:'护卫', short:'卫', desc:'左右相邻的我方单位不会被敌方陆军单位攻击,自身不受保护,直至该单位死亡。' }
};
function getKeywords(cardId) { const def = CARD_DB[cardId]; return (def && Array.isArray(def.keywords)) ? def.keywords : []; }
function hasKeyword(cardId, kwId) { return getKeywords(cardId).indexOf(kwId) >= 0; }
function getMaxAttacks(cardId) { return hasKeyword(cardId, 'double') ? 2 : 1; }
function keywordBadgesHTML(cardId) {
  const list = getKeywords(cardId);
  if (!list.length) return '';
  let s = '';
  for (const k of list) {
    const kw = KEYWORDS[k];
    if (!kw) continue;
    s += `<i class="kw kw-${k}" title="${kw.name}">${kw.short}</i>`;
  }
  return s;
}

/* ==================== 卡牌数据 ==================== */
const CARD_DB = {
  usa_1st_infantry: { name:'第1步兵师', cost:2, atk:2, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“大红一师”的名号响彻战场,是美军最早投入欧洲战场的部队之一。',
    story:'第1步兵师绰号“大红一师”,因肩章上的红色数字“1”得名。成立于1917年,二战中参加了北非登陆、西西里战役和诺曼底登陆,在奥马哈海滩付出惨重伤亡。' },
  usa_101st_airborne: { name:'第101空降师', cost:4, atk:3, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['guard'],
    desc:'绰号“呼啸之鹰”,诺曼底夜空中的精锐伞兵。',
    story:'第101空降师绰号“呼啸之鹰”,成立于1942年。诺曼底登陆夜,伞兵散落在诺曼底乡间仍迅速集结。巴斯托涅被围时,代理师长面对德军劝降只回了一个词:“Nuts!”' },
  usa_sherman: { name:'M4谢尔曼', cost:3, atk:3, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'美军装甲部队的中坚力量,以数量取胜的可靠坦克。',
    story:'M4谢尔曼中型坦克于1941年定型,是二战中美国生产数量最多的坦克,总产量接近五万辆。可靠、易维护、产量巨大。' },
  usa_p51_mustang: { name:'P-51野马', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'usa',
    keywords:['rush'],
    desc:'为轰炸机护航的远程战斗机,欧洲上空的银色猎手。',
    story:'P-51“野马”是二战中最优秀的活塞式战斗机之一,由北美航空公司研制。超长航程使其能全程护航至柏林并返回,被誉为“轰炸机之友”。' },
  usa_b17_flying_fortress: { name:'B-17空中堡垒', cost:5, atk:4, hp:5, type:'unit', unitType:'ranged', rarity:'legendary', nation:'usa',
    keywords:['guard'],
    desc:'重型轰炸机的主力,以密集编队承受着德军的防空炮火。',
    story:'B-17“空中堡垒”是波音公司研制的四发重型轰炸机,以强大的自卫火力和坚固结构闻名。欧洲战场上,B-17机群白天深入德国本土轰炸,损失极为惨重。' },
  usa_rangers: { name:'第5游骑兵营', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    keywords:['rush'],
    desc:'突击队中的精英,在奥马哈海滩的悬崖上攀爬前行。',
    story:'第5游骑兵营隶属于美国陆军游骑兵部队。1944年6月6日,该营C连攀爬霍克角悬崖,摧毁了被认为部署在那里的德军重炮。' },
  usa_82nd_airborne: { name:'第82空降师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['rush'],
    desc:'“全美师”,从西西里到尼米兹,哪里有硬仗哪里就有他们。',
    story:'第82空降师绰号“全美师”,成员来自当时美国全部48个州。二战中参加了西西里岛空降、萨勒诺登陆、诺曼底空降和“市场花园”行动。' },
  usa_hellcat: { name:'M18地狱猫', cost:3, atk:4, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['firststrike'],
    desc:'坦克歼击车中的速度之王,以伏击战术猎杀德军装甲部队。',
    story:'M18“地狱猫”以公路时速80公里著称,装甲薄弱但装备76毫米火炮,足以击穿大多数德军坦克的侧面和后方。' },
  usa_m7_priest: { name:'M7牧师', cost:3, atk:2, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'自行火炮,因车体上的机枪座外形酷似讲道坛而得名。',
    story:'M7自行火炮以M3李中型坦克为底盘,装备105毫米榴弹炮。英国名字“牧师”来源于其车体右侧突出的机枪座。' },
  usa_30th_infantry: { name:'第30步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    desc:'“老胡桃木师”,在连续作战天数上几乎超越了所有美军师。',
    story:'第30步兵师在欧洲战场连续作战超过300天,从诺曼底一直打到德国本土。德军称它为“罗斯福的党卫军”。' },
  usa_blue_devils: { name:'第88步兵师', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'绰号“蓝魔鬼”,在意大利战场上与德军山地部队反复拉锯。',
    story:'第88步兵师绰号“蓝魔鬼”,名称来源于蓝色肩章。1944年投入意大利战场,二战中伤亡超过15000人。' },
  usa_17th_infantry: { name:'第17步兵团', cost:1, atk:1, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'第7步兵师的主力团,参与了太平洋战场的多次两栖登陆。',
    story:'第17步兵团参加了阿图岛、夸贾林环礁、莱特岛和冲绳岛等多次两栖登陆作战。' },
  usa_naval_support: { name:'海军炮火支援', cost:3, atk:0, hp:0, type:'command', rarity:'common', nation:'usa',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:3 },
    desc:'作战令:点击敌方单位或敌方总部,战列舰主炮齐射,造成 3 点伤害。',
    story:'太平洋两栖作战中,美国海军的火力支援至关重要。战列舰、巡洋舰和驱逐舰会在登陆前对岛屿进行数小时炮击。' },
  usa_production_order: { name:'生产令', cost:1, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +1/+1。',
    story:'二战期间,美国凭借强大的工业能力成为“民主国家的兵工厂”。1942—1945年间生产了约30万架飞机、10万辆坦克。' },
  usa_war_bonds: { name:'战争债券', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'player_hq', effect:{ type:'heal_hq', value:6 },
    desc:'作战令:点击我方总部,恢复 6 点生命。',
    story:'为了筹措战争经费,美国政府发行了大量战争债券,共筹集了超过1800亿美元,占美国战争总开支的一半以上。' },
  usa_c47_skytrain: { name:'C-47运输机', cost:2, atk:1, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'空降行动的中坚力量,将伞兵和补给投向敌后。',
    story:'C-47“空中列车”是二战中最著名的运输机。诺曼底登陆和“市场花园”行动中,数百架C-47在夜空中编队飞行。' },
  usa_2nd_armored: { name:'第2装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['mobile'],
    desc:'“地狱之轮”,在巴顿将军麾下横扫欧洲。',
    story:'第2装甲师绰号“地狱之轮”,是美军最早的装甲师之一。突出部战役中在严寒中急行军,成功解救了巴斯托涅。' },
  usa_442nd_regiment: { name:'第442步兵团', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['rush'],
    desc:'由日裔美国人组成的传奇部队,用鲜血证明忠诚。',
    story:'第442步兵团是美国军事史上受勋最多的部队。法国孚日山脉中,该团为营救被围的“失落营”付出了惨重代价。共获超过18000枚勋章。' },
  usa_omaha_beach: { name:'奥马哈海滩', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +2/+0。',
    story:'奥马哈海滩是诺曼底登陆中伤亡最惨重的登陆点。第一波攻击几乎全军覆没,直到海军驱逐舰冒险靠近海岸直瞄射击才扭转局势。' },
  usa_airborne_doctrine: { name:'空降作战条令', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +1/+2。',
    story:'美军在二战中大规模运用空降部队,形成系统的空降作战理论。诺曼底两个空降师的成功空降为登陆部队创造了关键条件。' },
  usa_ambush: { name:'伏击圈', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'usa',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:2 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 2 点伤害。',
    story:'美军在太平洋岛屿和欧洲战场上常设置伏击阵地,利用地形和火力优势打击敌军前锋部队。' },
  usa_3rd_infantry: { name:'第3步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'绰号“马恩磐石”,从北非一路打到德国本土的老牌劲旅。',
    story:'第3步兵师绰号“马恩磐石”,源于一战马恩河战役中的顽强防守。二战中参加了北非、西西里、意大利南部和法国南部的作战。' },
  usa_4th_infantry: { name:'第4步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“常春藤师”,犹他海滩登陆的主力部队之一。',
    story:'第4步兵师绰号“常春藤师”,1944年6月6日在犹他海滩登陆,随后一路推进至巴黎并深入德国本土。' },
  usa_9th_infantry: { name:'第9步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“老可靠”,突出部战役中顶住德军反扑的中坚。',
    story:'第9步兵师绰号“老可靠”,在阿登森林中坚守关键路口,为盟军反击争取了宝贵时间。' },
  usa_29th_infantry: { name:'第29步兵师', cost:3, atk:3, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['guard'],
    desc:'“蓝灰师”,奥马哈海滩第一波冲击的部队。',
    story:'第29步兵师绰号“蓝灰师”,继承南北战争时期的历史血脉。在奥马哈海滩首日登陆中伤亡极为惨重。' },
  usa_45th_infantry: { name:'第45步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“雷鸟师”,西西里与南法战场上的美军劲旅。',
    story:'第45步兵师绰号“雷鸟师”,其成员多来自俄克拉荷马等州,二战中参加了西西里登陆、萨勒诺和法国南部作战。' },
  usa_34th_infantry: { name:'第34步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“红牛师”,在意大利山地战中与德军反复拉锯。',
    story:'第34步兵师绰号“红牛师”,在意大利战场攻占了卡西诺山周边阵地,作战极为艰苦。' },
  usa_36th_infantry: { name:'第36步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“德克萨斯师”,在意大利战场强渡拉皮多河。',
    story:'第36步兵师绰号“德克萨斯师”,1944年初强渡拉皮多河时遭受惨重伤亡,成为意大利战役中最惨烈的战斗之一。' },
  usa_1st_marine: { name:'第1陆战师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['firststrike'],
    desc:'“老资格”,瓜岛、佩里琉、冲绳的陆战主力。',
    story:'第1陆战师是美军历史最悠久的陆战师,二战中参加了瓜达尔卡纳尔、格洛斯特角、佩里琉和冲绳等血战。' },
  usa_2nd_marine: { name:'第2陆战师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['firststrike'],
    desc:'塔拉瓦环礁的血战中锤炼出的精锐陆战师。',
    story:'第2陆战师在塔拉瓦环礁登陆战中付出惨重代价,也由此总结出改进两栖登陆战术的经验。' },
  usa_3rd_marine: { name:'第3陆战师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    desc:'关岛与硫磺岛上的陆战劲旅。',
    story:'第3陆战师参加了关岛收复战和硫磺岛战役,在折钵山下与日军展开了残酷的坑道战。' },
  usa_4th_marine: { name:'第4陆战师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    desc:'马绍尔与塞班岛登陆的中坚力量。',
    story:'第4陆战师参加了罗伊-纳穆尔、塞班和提尼安等岛屿的登陆作战,伤亡率居高不下。' },
  usa_5th_marine: { name:'第5陆战师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['guard'],
    desc:'硫磺岛折钵山升旗的部队。',
    story:'第5陆战师在硫磺岛战役中承担主攻任务,折钵山升旗的经典照片即出自该师官兵。' },
  usa_1st_cavalry: { name:'第1骑兵师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['mobile'],
    desc:'虽名为骑兵,实为步兵师,太平洋战场的主力。',
    story:'第1骑兵师在二战中已改为步兵编制,参加了阿德默勒尔蒂群岛、莱特岛和吕宋岛等战役。' },
  usa_1st_armored: { name:'第1装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['guard'],
    desc:'“老铁壳”,美军最早的装甲师。',
    story:'第1装甲师绰号“老铁壳”,二战中参加了北非、西西里和西欧战场的一系列作战,是美军装甲部队的中坚。' },
  usa_3rd_armored: { name:'第3装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['rush'],
    desc:'“矛头师”,巴顿麾下的装甲铁拳。',
    story:'第3装甲师绰号“矛头师”,在巴顿指挥下于突出部战役中急行军救援巴斯托涅,创造了装甲部队的机动典范。' },
  usa_4th_armored: { name:'第4装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['mobile'],
    desc:'突出部战役中率先打破德军包围的装甲师。',
    story:'第4装甲师在1944年12月突出部战役中从南翼发起反击,率先与巴斯托涅守军会合。' },
  usa_6th_armored: { name:'第6装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'欧洲战场上美军装甲部队的中坚之一。',
    story:'第6装甲师于1944年底投入欧洲战场,参加了阿登反击和跨越莱茵河等作战。' },
  usa_7th_armored: { name:'第7装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'从诺曼底一路推进到德国本土的装甲师。',
    story:'第7装甲师在诺曼底登陆后参与了眼镜蛇行动,随后穿越法国和比利时直抵德国边境。' },
  usa_10th_armored: { name:'第10装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'巴斯托涅解围战中的关键装甲力量。',
    story:'第10装甲师在突出部战役中从南面发起进攻,是首批突入巴斯托涅包围圈的部队之一。' },
  usa_11th_armored: { name:'第11装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'突出部战役中驰援巴斯托涅的装甲部队。',
    story:'第11装甲师在严寒和冰雪中强行军,为巴斯托涅守军打开了生命通道。' },
  usa_506_pir: { name:'第506伞降步兵团', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['guard'],
    desc:'“呼啸之鹰”的核心团,巴斯托涅的坚守者。',
    story:'第506伞降步兵团隶属第101空降师,在巴斯托涅被围期间坚守阵地,代理师长麦考利夫准将回以“Nuts!”拒绝劝降。' },
  usa_505_pir: { name:'第505伞降步兵团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['rush'],
    desc:'第82空降师的主力伞兵团。',
    story:'第505伞降步兵团参加了西西里、萨勒诺、诺曼底和“市场花园”等一系列空降作战。' },
  usa_17_abn: { name:'第17空降师', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['rush'],
    desc:'“市场花园”行动中投入的年轻空降师。',
    story:'第17空降师于1944年8月组建,在“市场花园”行动中首次参战,负责夺取荷兰境内的多处桥梁。' },
  usa_11_abn: { name:'第11空降师', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['rush'],
    desc:'太平洋战场的空降师,吕宋岛空降的奇兵。',
    story:'第11空降师在太平洋战场执行了吕宋岛空降作战,是美军在太平洋地区少有的空降行动。' },
  usa_13_abn: { name:'第13空降师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'训练有素但未及参战的空降部队。',
    story:'第13空降师于1943年组建,长期担任战略预备队,战争结束前未能投入实战。' },
  usa_m10_wolverine: { name:'M10狼獾', cost:3, atk:4, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'美军广泛使用的坦克歼击车,敞开式炮塔。',
    story:'M10“狼獾”装备76毫米火炮,是美军坦克歼击车部队的主力,在北非和欧洲战场大量使用。' },
  usa_m36_jackson: { name:'M36杰克逊', cost:4, atk:5, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['firststrike'],
    desc:'装备90毫米火炮,足以击穿虎式坦克的正面装甲。',
    story:'M36“杰克逊”换装90毫米火炮,是美军在二战中火力最强的坦克歼击车之一。' },
  usa_m26_pershing: { name:'M26潘兴', cost:5, atk:5, hp:6, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['guard'],
    desc:'美军在二战中投入的重型坦克,德军的强劲对手。',
    story:'M26“潘兴”装备90毫米火炮和厚重装甲,1945年初投入欧洲战场,是美军少数能与虎式抗衡的坦克。' },
  usa_m24_chaffee: { name:'M24霞飞', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    keywords:['mobile'],
    desc:'轻巧灵活的轻型坦克,擅长侦察与侧翼包抄。',
    story:'M24“霞飞”是美军在二战后期装备的轻型坦克,火力和机动性均优于早期的M5斯图亚特。' },
  usa_m5_stuart: { name:'M5斯图亚特', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    keywords:['mobile'],
    desc:'“甜心”,英军对这款轻型坦克的爱称。',
    story:'M5斯图亚特是美军轻型坦克的代表,装甲薄弱但速度极快,大量通过租借法案提供给盟国。' },
  usa_m3_lee: { name:'M3李', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'车体侧面装炮的早期中型坦克,被戏称为“七兄弟棺材”。',
    story:'M3李中型坦克因车高体大、装甲薄弱而被士兵戏称为“七兄弟棺材”,但在北非战场初期发挥了重要作用。' },
  usa_m8_greyhound: { name:'M8灰狗', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    keywords:['mobile'],
    desc:'六轮装甲车,负责侦察与快速火力支援。',
    story:'M8“灰狗”装甲车装备37毫米火炮,机动性强,广泛用于战场侦察和侧翼掩护。' },
  usa_m4a3e8: { name:'M4A3E8谢尔曼', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    desc:'换装长身管76毫米火炮的谢尔曼改进型。',
    story:'M4A3E8装备76毫米长身管火炮和HVSS悬挂系统,是谢尔曼系列中综合性能最好的型号之一。' },
  usa_jumbo: { name:'M4A3E2巨无霸', cost:4, atk:3, hp:7, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['guard'],
    desc:'装甲加厚的突击坦克,用于突破德军防线。',
    story:'M4A3E2“巨无霸”正面装甲厚度大幅增加,专门用于伴随步兵突破德军筑垒阵地。' },
  usa_7th_infantry_rgt: { name:'第7步兵团', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'第3步兵师的主力团,作战经验丰富。',
    story:'第7步兵团隶属于第3步兵师,参加了北非、西西里和西欧战场的一系列作战。' },
  usa_16th_infantry: { name:'第16步兵团', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“第一”团,美军历史最悠久的步兵团之一。',
    story:'第16步兵团绰号“第一”团,历史可追溯到1798年,二战中隶属第1步兵师。' },
  usa_18th_infantry: { name:'第18步兵团', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'第1步兵师的主力团之一,冲锋在最前线。',
    story:'第18步兵团随第1步兵师参加了奥马哈海滩登陆,在激烈战斗中伤亡惨重。' },
  usa_26th_infantry: { name:'第26步兵团', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“扬基师”的主力团,来自新英格兰。',
    story:'第26步兵团隶属第1步兵师前身部队,其成员多来自美国东北部各州。' },
  usa_28th_infantry: { name:'第28步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“拱心石师”,宾夕法尼亚国民警卫队改编。',
    story:'第28步兵师绰号“拱心石师”,在法国和德国边境的许特根森林中经历了美军最惨烈的森林战。' },
  usa_35th_infantry: { name:'第35步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“圣塔菲师”,从诺曼底打到易北河。',
    story:'第35步兵师绰号“圣塔菲师”,参加了诺曼底、阿登和德国本土的作战。' },
  usa_63rd_infantry: { name:'第63步兵师', cost:2, atk:2, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“血与火师”,在欧洲战场长期承担防御任务。',
    story:'第63步兵师绰号“血与火师”,参加了法国北部和德国本土的作战,俘虏德军超过三万人。' },
  usa_84th_infantry: { name:'第84步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“铁轨拆分者师”,突出部战役中的坚守部队。',
    story:'第84步兵师绰号“铁轨拆分者师”,在突出部战役中坚守马尔梅迪一带,阻止了德军装甲部队的突破。' },
  usa_90th_infantry: { name:'第90步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'“硬汉师”,诺曼底灌木丛战中锤炼出的部队。',
    story:'第90步兵师绰号“硬汉师”,在诺曼底丛林地带与德军展开长期消耗战。' },
  usa_99th_infantry: { name:'第99步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['guard'],
    desc:'“棋盘师”,突出部战役中首当其冲的部队。',
    story:'第99步兵师绰号“棋盘师”,在1944年12月德军阿登反扑中首当其冲,在埃尔森伯恩岭顽强抵抗。' },
  usa_106th_infantry: { name:'第106步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'突出部战役中遭受重创的年轻部队。',
    story:'第106步兵师是美军在欧洲战场最晚参战的师之一,在突出部战役初期被德军合围,损失惨重。' },
  usa_1st_ssf: { name:'第1特种部队', cost:4, atk:4, hp:3, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['stealth'],
    desc:'深入缅甸丛林的远程渗透部队。',
    story:'第1特种部队(“梅里尔掠夺者”前身)在缅甸战场执行远程渗透任务,与日军在丛林中周旋。' },
  usa_devils_brigade: { name:'魔鬼旅', cost:4, atk:4, hp:3, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['rush'],
    desc:'美加联合组建的突击队,专门执行最危险的任务。',
    story:'“魔鬼旅”由美国和加拿大士兵共同组成,在意大利战场执行了多次突击和侦察任务。' },
  usa_marauaders: { name:'梅里尔突击队', cost:4, atk:4, hp:3, type:'unit', unitType:'land', rarity:'epic', nation:'usa',
    keywords:['stealth'],
    desc:'缅甸丛林中的远程渗透部队,以少胜多。',
    story:'第5307混合支队(梅里尔突击队)在缅甸北部执行远程渗透作战,牵制了大量日军兵力。' },
  usa_alamo_scouts: { name:'阿拉莫侦察兵', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'usa',
    keywords:['mobile'],
    desc:'深入敌后执行侦察任务的小型精英部队。',
    story:'阿拉莫侦察兵由志愿者组成,专门执行深入敌后的侦察任务,为登陆作战提供情报。' },
  usa_p47_thunderbolt: { name:'P-47雷电', cost:4, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'usa',
    keywords:['rush'],
    desc:'厚重的战斗轰炸机,低空扫射德军纵队。',
    story:'P-47“雷电”是二战中最重的单发战斗机,以强大的火力和俯冲性能著称,广泛用于对地攻击。' },
  usa_p38_lightning: { name:'P-38闪电', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    keywords:['mobile'],
    desc:'双发双尾撑战斗机,太平洋上空的远程猎手。',
    story:'P-38“闪电”航程极远,在太平洋战场执行远程护航和拦截任务,击落了山本五十六的座机。' },
  usa_p40_warhawk: { name:'P-40战鹰', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'飞虎队的座机,在缅甸和中国上空作战。',
    story:'P-40“战鹰”性能中庸但数量庞大,美国志愿航空队(飞虎队)曾驾驶该机在中国和缅甸上空作战。' },
  usa_f4u_corsair: { name:'F4U海盗', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    desc:'倒海鸥翼的舰载战斗机,太平洋战场的“死神”。',
    story:'F4U“海盗”以独特的倒海鸥翼设计著称,在日本飞行员口中被称为“呼啸死神”。' },
  usa_f6f_hellcat: { name:'F6F地狱猫', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'usa',
    keywords:['double'],
    desc:'太平洋战场上击落日军飞机最多的舰载机。',
    story:'F6F“地狱猫”在太平洋战争中共击落超过五千架敌机,是美军最成功的舰载战斗机。' },
  usa_b24_liberator: { name:'B-24解放者', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    desc:'产量最大的四发重型轰炸机,作战范围广泛。',
    story:'B-24“解放者”总产量超过一万八千架,是二战中产量最大的美国军用飞机,广泛用于战略轰炸和反潜巡逻。' },
  usa_b25_mitchell: { name:'B-25米切尔', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    keywords:['rush'],
    desc:'中程轰炸机,杜立特空袭东京的座机。',
    story:'B-25“米切尔”是中程轰炸机的代表,1942年杜立特中校率该型机从航母起飞空袭东京。' },
  usa_b26_marauder: { name:'B-26掠夺者', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'速度快但着舰困难的的中型轰炸机。',
    story:'B-26“掠夺者”速度快、翼载高,起降事故率一度很高,但参战后表现良好。' },
  usa_b29_superfortress: { name:'B-29超级堡垒', cost:7, atk:7, hp:5, type:'unit', unitType:'ranged', rarity:'legendary', nation:'usa',
    keywords:['guard'],
    desc:'轰炸日本本土的战略利器,载弹量与航程空前。',
    story:'B-29“超级堡垒”是二战中最先进的重型轰炸机,装备增压座舱和遥控炮塔,执行了对日本本土的战略轰炸及投掷原子弹的任务。' },
  usa_a20_havoc: { name:'A-20浩劫', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'低空攻击机,以快速突袭见长。',
    story:'A-20“浩劫”是美军在二战初期使用的中型攻击机,低空性能良好,广泛提供给盟国使用。' },
  usa_a26_invader: { name:'A-26入侵者', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    keywords:['rush'],
    desc:'太平洋战场上的快速攻击机,火力凶猛。',
    story:'A-26“入侵者”在二战后期投入太平洋战场,速度快、载弹量大,是美军最优秀的轻型攻击机之一。' },
  usa_c46_commando: { name:'C-46突击队员', cost:2, atk:1, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'运输机,飞越“驼峰”航线的主力。',
    story:'C-46“突击队员”载重能力强,在飞越喜马拉雅山的“驼峰”航线中承担了大量运输任务。' },
  usa_glider_cg4a: { name:'CG-4A滑翔机', cost:2, atk:2, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'悄无声息地将伞兵和装备送入敌后。',
    story:'CG-4A滑翔机由木质和帆布制成,在诺曼底和“市场花园”行动中大量使用。' },
  usa_m12_gmc: { name:'M12自行火炮', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'装备155毫米榴弹炮的自行火炮。',
    story:'M12自行火炮以M3中型坦克为底盘,装备155毫米榴弹炮,主要用于摧毁德军坚固工事。' },
  usa_m40_gmc: { name:'M40自行火炮', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    desc:'装备155毫米长身管火炮的重型自行火炮。',
    story:'M40自行火炮以M4谢尔曼为底盘,装备155毫米长身管火炮,火力极为强悍。' },
  usa_m41_gorilla: { name:'M41大猩猩', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'轻型自行火炮,用于伴随装甲部队作战。',
    story:'M41自行火炮以M24霞飞轻型坦克为底盘,装备155毫米榴弹炮,机动性较好。' },
  usa_m43: { name:'M43自行火炮', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    desc:'装备203毫米榴弹炮的重型自行火炮。',
    story:'M43自行火炮装备203毫米榴弹炮,专门用于摧毁德军坚固筑垒阵地。' },
  usa_long_tom: { name:'155毫米长汤姆', cost:4, atk:5, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    desc:'美军最优秀的野战重炮,射程与精度俱佳。',
    story:'M1 155毫米“长汤姆”野战炮是美军在二战中最重要的重型火炮,战后仍在多国服役。' },
  usa_105_howitzer: { name:'105毫米榴弹炮', cost:3, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'美军步兵师的标准支援火炮。',
    story:'M2 105毫米榴弹炮是美军步兵师的标准师属火炮,机动性好、威力适中。' },
  usa_90mm_aa: { name:'90毫米高射炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'防空利器,也能用于反坦克作战。',
    story:'M1 90毫米高射炮是美军在二战中最重要的重型防空火炮,也可用于对付德军坦克。' },
  usa_40mm_bofors: { name:'40毫米博福斯', cost:2, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'中口径防空炮,对低空目标效果显著。',
    story:'40毫米博福斯高射炮被盟军广泛使用,是二战中最好的中口径防空武器之一。' },
  usa_catalina: { name:'PBY卡特琳娜', cost:3, atk:2, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'水上巡逻机,发现并跟踪德军潜艇。',
    story:'PBY“卡特琳娜”水上飞机在太平洋和大西洋执行反潜巡逻任务,曾发现多艘德军和日军舰船。' },
  usa_avenger: { name:'TBF复仇者', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    desc:'舰载鱼雷轰炸机,中途岛后成为美军主力。',
    story:'TBF“复仇者”是美军在二战中最主要的舰载鱼雷轰炸机,在太平洋战场的对舰攻击中表现出色。' },
  usa_helldiver: { name:'SB2C地狱俯冲者', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    desc:'舰载俯冲轰炸机,火力强悍但初期故障频发。',
    story:'SB2C“地狱俯冲者”虽然早期存在诸多问题,但在战争后期成为美军舰载俯冲轰炸的主力。' },
  usa_dauntless: { name:'SBD无畏', cost:3, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'usa',
    keywords:['rush'],
    desc:'中途岛海战的功臣,一举击沉四艘日军航母。',
    story:'SBD“无畏”俯冲轰炸机在1942年中途岛海战中立下奇功,短短数分钟内击沉日军四艘主力航母。' },
  usa_wildcat: { name:'F4F野猫', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'战争初期的舰载战斗机,瓜岛上的坚守者。',
    story:'F4F“野猫”在太平洋战争初期性能并不占优,但凭借坚固结构和战术优势,在瓜岛战役中与零式战机周旋。' },
  usa_black_widow: { name:'P-61黑寡妇', cost:5, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'usa',
    keywords:['stealth'],
    desc:'装备雷达的夜间战斗机,在黑暗中猎杀敌机。',
    story:'P-61“黑寡妇”是美军专为夜间作战设计的战斗机,配备机载雷达,在太平洋和欧洲战场均有使用。' },
  usa_kingcobra: { name:'P-63眼镜王蛇', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    desc:'后期援苏战斗机,在东线战场作战。',
    story:'P-63“眼镜王蛇”主要通过租借法案提供给苏联,苏军曾用它参加了远东对日作战。' },
  usa_mustang_d: { name:'P-51D野马', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'usa',
    keywords:['rush'],
    desc:'为轰炸机全程护航的远程战斗机。',
    story:'P-51D“野马”换装气泡座舱和六挺机枪,是二战中后期美军最重要的远程护航战斗机。' },
  usa_thunderbolt_d: { name:'P-47D雷电', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'usa',
    keywords:['guard'],
    desc:'加装副油箱后的远程型雷电。',
    story:'P-47D加装副油箱后航程大幅提升,既能执行护航任务,也能对地攻击。' },
  usa_lend_lease: { name:'租借法案', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'player_hq', effect:{ type:'heal_hq', value:5 },
    desc:'作战令:点击我方总部,恢复 5 点生命。',
    story:'1941年美国通过租借法案,向盟国提供武器和物资援助,总额超过500亿美元,对反法西斯战争胜利起到了关键作用。' },
  usa_arsenal_democracy: { name:'民主兵工厂', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +1/+1。',
    story:'罗斯福总统称美国为“民主国家的兵工厂”,二战期间美国工业产能全开,为盟军提供了海量武器装备。' },
  usa_manhattan: { name:'曼哈顿计划', cost:6, atk:0, hp:0, type:'command', rarity:'epic', nation:'usa',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:8 },
    desc:'作战令:点击敌方单位或敌方总部,造成 8 点伤害。',
    story:'曼哈顿计划是美国研制原子弹的绝密工程,汇集了奥本海默、费米等众多科学家,最终研制出人类第一颗原子弹。' },
  usa_dday: { name:'诺曼底登陆', cost:5, atk:0, hp:0, type:'command', rarity:'epic', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:3, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +3/+1。',
    story:'1944年6月6日,盟军在诺曼底实施“霸王行动”,是人类历史上规模最大的两栖登陆作战。' },
  usa_operation_torch: { name:'火炬行动', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'player_hq', effect:{ type:'heal_hq', value:4 },
    desc:'作战令:点击我方总部,恢复 4 点生命。',
    story:'1942年11月,美英联军在北非实施“火炬行动”,是美军在欧洲战区的首次大规模两栖登陆。' },
  usa_operation_overlord: { name:'霸王行动', cost:5, atk:0, hp:0, type:'command', rarity:'epic', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +2/+2。',
    story:'“霸王行动”是诺曼底登陆的正式代号,艾森豪威尔将军担任盟军最高统帅。' },
  usa_battle_bulge: { name:'突出部战役', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:0, hp:3 },
    desc:'作战令:点击我方总部,全体单位 +0/+3。',
    story:'1944年12月,德军在阿登地区发起最后反扑,美军在严寒中顽强抵抗,最终粉碎了德军的进攻。' },
  usa_market_garden: { name:'市场花园行动', cost:4, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +2/+0。',
    story:'1944年9月,盟军发起“市场花园”行动,试图夺取荷兰境内的一系列桥梁,但最终未能成功。' },
  usa_island_hopping: { name:'跳岛战术', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'usa',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:4 },
    desc:'作战令:点击敌方单位或敌方总部,造成 4 点伤害。',
    story:'美军在太平洋战场采用“跳岛战术”,绕过日军重兵防守的岛屿,逐一夺取关键据点。' },
  usa_amphibious: { name:'两栖登陆', cost:3, atk:0, hp:0, type:'command', rarity:'common', nation:'usa',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +1/+0。',
    story:'美军在太平洋和欧洲战场都进行了大量两栖登陆作战,积累了丰富的登陆经验。' },
  usa_radar_alert: { name:'雷达警戒', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'usa',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:3 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 3 点。',
    story:'美军舰艇和岛屿基地广泛装备雷达,能够提前发现来袭的日军飞机和舰船。' },
  usa_ambush_patrol: { name:'巡逻伏击', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'usa',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:3 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 3 点伤害。',
    story:'美军巡逻队在太平洋岛屿和欧洲战场上常设伏击点,打击德军和日军的巡逻队和补给队。' },
  usa_antitank_ambush: { name:'反坦克伏击', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'usa',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 4 点伤害。',
    story:'美军坦克歼击车部队擅长利用地形设伏,以先发制人的火力打击德军装甲部队。' },
  usa_flak_barrage: { name:'防空火力网', cost:2, atk:0, hp:0, type:'counter', rarity:'common', nation:'usa',
    trigger:'enemy_deploy', effect:{ type:'damage_hq', value:2 },
    desc:'应变:布下后,敌方部署单位时触发,对敌方总部造成 2 点伤害。',
    story:'美军在重要港口和机场周围部署密集的高射炮火力网,有效抵御了敌方空袭。' },
  usa_last_stand: { name:'最后防线', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'usa',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:4 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 4 点。',
    story:'在巴斯托涅和瓜达尔卡纳尔等战役中,美军在极端困难的条件下坚守阵地,最终扭转战局。' },
  usa_m3_halftrack: { name:'M3半履带车', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    keywords:['mobile'],
    desc:'装甲输送车,为步兵提供机动和防护。',
    story:'M3半履带车是美军装甲步兵的主要输送工具,也被改装为多种用途的支援车辆。' },
  usa_dukw: { name:'DUKW两栖车', cost:2, atk:1, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'水陆两栖运输车,登陆作战中的后勤主力。',
    story:'DUKW水陆两栖车能在海上航行并直接驶上滩头,是诺曼底和太平洋登陆作战中的后勤生命线。' },
  usa_jeep: { name:'威利斯吉普', cost:1, atk:1, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    keywords:['mobile'],
    desc:'“战场上的万能车”,侦察、通信、运输无所不能。',
    story:'威利斯MB吉普车结构简单、可靠耐用,被称为“二战中最重要的美国武器之一”。' },
  usa_bazooka: { name:'巴祖卡', cost:2, atk:3, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'usa',
    desc:'肩扛式反坦克火箭筒,步兵的近身反装甲利器。',
    story:'“巴祖卡”火箭筒使步兵具备了近距离反坦克能力,德军也仿制了类似武器(“坦克杀手”)。' },
  usa_quad50: { name:'四联装50机枪', cost:2, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'usa',
    desc:'四管12.7毫米机枪,防空与压制两用。',
    story:'M45四联装12.7毫米机枪塔是美军重要的低空防空武器,也常用于压制地面目标。' },
      /* ==================== 苏联 · 新增卡牌(100 张) ==================== */
  ussr_316_rifle: { name:'第316步兵师', cost:3, atk:3, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['guard'],
    desc:'“潘菲洛夫师”,在莫斯科城下以血肉之躯阻挡德军装甲纵队。',
    story:'第316步兵师由潘菲洛夫少将指挥,1941年11月在杜博谢科沃车站附近与德军坦克激战。该师因作战英勇被授予“近卫”称号,改称第8近卫步兵师。' },
  ussr_150_rifle: { name:'第150步兵师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'ussr',
    keywords:['rush'],
    desc:'将红旗插上国会大厦的部队。',
    story:'第150步兵师在1945年柏林战役中攻入国会大厦,叶戈罗夫和坎塔里亚两名士兵将红旗插上了大厦穹顶,成为苏联卫国战争胜利的标志性画面。' },
  ussr_13_guards: { name:'第13近卫步兵师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'ussr',
    keywords:['guard'],
    desc:'罗季姆采夫麾下的钢铁之师,斯大林格勒巷战的中坚。',
    story:'第13近卫步兵师在罗季姆采夫少将指挥下渡过伏尔加河,投入斯大林格勒巷战,与德军在马马耶夫岗反复争夺,战至最后一人。' },
  ussr_1_guards: { name:'第1近卫步兵师', cost:3, atk:3, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['rush'],
    desc:'首批获得“近卫”称号的红军部队之一。',
    story:'第1近卫步兵师前身为第100步兵师,1941年9月因在叶利尼亚突出部反击战中表现出色,被授予近卫称号。' },
  ussr_8_guards: { name:'第8近卫步兵师', cost:3, atk:3, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['guard'],
    desc:'潘菲洛夫师的后继番号,在东线屡建奇功。',
    story:'第8近卫步兵师前身为潘菲洛夫第316步兵师,改番号后继续在东线作战,参加了波罗的海沿岸的一系列攻势。' },
  ussr_62_army: { name:'第62集团军', cost:5, atk:5, hp:6, type:'unit', unitType:'land', rarity:'legendary', nation:'ussr',
    keywords:['guard'],
    desc:'崔可夫指挥下的斯大林格勒守军,被压缩在伏尔加河畔仍死战不退。',
    story:'第62集团军在崔可夫中将指挥下坚守斯大林格勒,将指挥部设在伏尔加河岸边,誓言“伏尔加河对岸没有我们的土地”。' },
  ussr_siberian: { name:'西伯利亚步兵', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'从远东调来的精锐,在严寒中战斗力不减。',
    story:'1941年冬天,苏军从远东调来多个西伯利亚师,在莫斯科反攻中投入战斗。这些部队习惯于严寒天气,装备精良,士气高昂。' },
  ussr_smg: { name:'冲锋枪手', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['rush'],
    desc:'手持波波沙冲锋枪的近战精锐,擅长城市巷战。',
    story:'PPSh-41“波波沙”冲锋枪是苏军在二战中产量最大的冲锋枪,结构简单、可靠耐用,成为苏军步兵的标志性武器。' },
  ussr_sapper: { name:'工兵营', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'负责开辟通路、排除地雷的工程部队。',
    story:'苏军工兵在突破德军筑垒阵地时承担危险的开路任务,也负责构筑防御阵地和架设桥梁。' },
  ussr_ptrs: { name:'反坦克枪手', cost:2, atk:4, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['firststrike'],
    desc:'手持14.5毫米反坦克枪,专打德军坦克侧后。',
    story:'PTRD-41反坦克枪使用14.5毫米弹药,能击穿德军轻型坦克的装甲,是苏军步兵反装甲的重要手段。' },
  ussr_flamethrower: { name:'火焰喷射兵', cost:3, atk:5, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    desc:'清除地堡和工事的毁灭性兵种。',
    story:'苏军火焰喷射兵在攻坚作战中负责摧毁德军地堡和火力点,近距离作战杀伤力极强,但自身伤亡率也很高。' },
  ussr_scout: { name:'侦察兵', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['mobile'],
    desc:'深入敌后,为指挥部提供关键情报。',
    story:'苏军侦察兵经常深入敌后数公里,潜伏观察德军部署,为炮兵和航空兵提供精确目标。' },
  ussr_politruk: { name:'政治委员', cost:2, atk:0, hp:0, type:'command', rarity:'common', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +2/+0。',
    story:'政治委员负责部队的政治教育,在战斗中带头冲锋鼓舞士气。1942年后政治委员制度改为政治副职,但仍在部队中发挥重要作用。' },
  ussr_women_aa: { name:'女子高射炮兵团', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'由女性组成的防空部队,守卫城市上空。',
    story:'二战期间大量苏联妇女加入防空部队,操纵高射炮和探照灯,为保卫莫斯科、列宁格勒等城市做出了重要贡献。' },
  ussr_ski_battalion: { name:'滑雪营', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['mobile'],
    desc:'在冬季雪原上机动作战,出其不意打击德军侧翼。',
    story:'苏军组建了多个滑雪营,利用冬季雪地机动作战,在莫斯科反攻和北方战线作战中表现出色。' },
  ussr_airborne_guards: { name:'近卫空降兵', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'epic', nation:'ussr',
    keywords:['rush'],
    desc:'从天而降的精锐部队,在第聂伯河空降中付出惨重代价。',
    story:'1943年9月,苏军在第聂伯河实施大规模空降作战,近卫空降兵在德军防空火力下跳伞,伤亡惨重仍坚持作战。' },
  ussr_militia: { name:'民兵师', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'由工人和市民组成的志愿部队,用血肉之躯守卫城市。',
    story:'莫斯科、列宁格勒和斯大林格勒都组建了民兵师,成员多为未经训练的工人和市民,却在保卫城市的战斗中英勇作战。' },
  ussr_24_rifle: { name:'第24步兵师', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'战争初期在东线顽强抵抗德军的老牌部队。',
    story:'第24步兵师在1941年夏天德军闪击战中顽强抵抗,后参加了莫斯科保卫战等一系列作战。' },
  ussr_100_rifle: { name:'第100步兵师', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'首个近卫步兵师的前身,在叶利尼亚反击战中表现突出。',
    story:'第100步兵师于1941年9月成为首批被授予近卫称号的部队之一,后改编为第1近卫步兵师。' },
  ussr_42_rifle: { name:'第42步兵师', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'列宁格勒前线的坚守部队,在围城中坚持作战。',
    story:'第42步兵师在列宁格勒围城期间坚守普尔科沃高地,是保卫该城的主要部队之一。' },
  ussr_comm: { name:'通信兵', cost:1, atk:1, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'在炮火中架设线路,保障指挥畅通。',
    story:'通信兵在战场上负责架设有线电话线路,常常冒着炮火爬出战壕检修线路,伤亡率极高。' },
  ussr_medic: { name:'卫生兵', cost:1, atk:1, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'在枪林弹雨中抢救伤员,被称为“战地白衣天使”。',
    story:'苏军女卫生兵在战场上冒着生命危险抢救伤员,许多人在前线阵亡。她们的勇敢事迹激励了无数士兵。' },
  ussr_combat_engineer: { name:'战斗工兵', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    desc:'携带爆破器材冲锋在前,专攻德军筑垒工事。',
    story:'苏军战斗工兵在攻坚作战中携带炸药包和火焰喷射器,负责摧毁德军的地堡和火力点,伤亡率极高。' },
  ussr_at_rifle_squad: { name:'反坦克枪小队', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['firststrike'],
    desc:'两人一组,操作反坦克枪伏击德军装甲。',
    story:'反坦克枪小队通常两人编组,一人射击一人装填,利用地形伏击德军坦克侧后装甲。' },
  ussr_shock_troop: { name:'突击群', cost:3, atk:4, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['rush'],
    desc:'由多兵种混编的强击分队,专攻德军据点。',
    story:'苏军在战争中后期组建突击群,将步兵、工兵、火焰喷射兵和坦克混编,用于突破德军坚固防御。' },
  ussr_t34: { name:'T-34坦克', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'ussr',
    keywords:['mobile'],
    desc:'倾斜装甲的革命性设计,苏联装甲部队的绝对主力。',
    story:'T-34是二战中最具影响力的坦克设计之一。1941年德军首次遭遇T-34时大为震惊,共生产超过5万辆。' },
  ussr_is2: { name:'IS-2重型坦克', cost:6, atk:6, hp:7, type:'unit', unitType:'land', rarity:'legendary', nation:'ussr',
    keywords:['guard'],
    desc:'装备122毫米重炮,专为突破德军防线而生的钢铁猛兽。',
    story:'IS-2装备122毫米火炮。1945年柏林战役中率先冲入柏林市区,成为苏联胜利的象征。' },
  ussr_kv1: { name:'KV-1坦克', cost:4, atk:3, hp:7, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['guard'],
    desc:'战争初期的钢铁堡垒,德军的反坦克炮在它面前束手无策。',
    story:'KV-1在1941年让德军的37毫米反坦克炮束手无策。拉塞尼艾战役中,一辆KV-1独自阻挡德军第6装甲师整整一天。' },
  ussr_il2_sturmovik: { name:'伊尔-2强击机', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    keywords:['rush'],
    desc:'“飞行坦克”,在低空撕碎德军装甲纵队。',
    story:'伊尔-2是二战中产量最大的军用飞机,共生产超过36000架。德军飞行员称它为“黑色死神”。' },
  ussr_guards_rifles: { name:'近卫步兵', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['rush'],
    desc:'获得“近卫”称号的精锐部队,在战斗中总是冲在最前面。',
    story:'“近卫”是苏联红军中最高荣誉的称号之一,授予在战斗中表现英勇的部队。近卫步兵师通常在关键突破中承担最艰巨的任务。' },
  ussr_sniper: { name:'狙击手', cost:2, atk:4, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['stealth'],
    desc:'隐藏在废墟中的死神,一枪毙命,让德军不敢露头。',
    story:'最著名的苏联狙击手瓦西里·扎伊采夫在斯大林格勒战役中确认击毙了225名敌军,其中包括11名德军狙击手。' },
  ussr_katyusha: { name:'喀秋莎火箭炮', cost:4, atk:5, hp:2, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    desc:'齐射时如暴雨倾盆,覆盖整个区域,是德军的噩梦。',
    story:'“喀秋莎”正式型号为BM-13,能在极短时间内倾泻大量火箭弹,首次使用于1941年奥尔沙战役。' },
  ussr_penal_battalion: { name:'惩戒营', cost:1, atk:2, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['rush'],
    desc:'由罪犯和违纪士兵组成,用鲜血洗刷罪过。',
    story:'惩戒营成员包括被军事法庭判罪的士兵和军官,被派往最危险的战斗区域,伤亡率极高。' },
  ussr_partisans: { name:'游击队', cost:1, atk:1, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['stealth'],
    desc:'在德军后方活动的民间武装,破坏铁路和补给线。',
    story:'1943年,游击队发动了大规模的“铁路战争”,一夜之间破坏了数千段铁轨,严重迟滞了德军的调动。' },
  ussr_zhukov: { name:'朱可夫元帅', cost:5, atk:0, hp:0, type:'command', rarity:'legendary', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +2/+2。',
    story:'朱可夫指挥了莫斯科保卫战、斯大林格勒战役、库尔斯克会战和柏林战役等一系列决定性战役。' },
  ussr_stalingrad: { name:'斯大林格勒', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'heal_hq', value:8 },
    desc:'作战令:点击我方总部,恢复 8 点生命。',
    story:'斯大林格勒战役是二战的转折点。苏军发动“天王星”行动,合围了德军第6集团军,迫使保卢斯元帅投降。' },
  ussr_kursk: { name:'库尔斯克', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:3, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +3/+0。',
    story:'库尔斯克会战是史上规模最大的坦克战役。德军最终未能突破苏军防线,从此在东线彻底丧失战略主动权。' },
  ussr_moscow_defense: { name:'莫斯科保卫战', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:0, hp:3 },
    desc:'作战令:点击我方总部,全体单位 +0/+3。',
    story:'1941年冬天,苏军从西伯利亚调来精锐部队,12月发动反攻,将德军击退了数百公里,打破了闪击战的神话。' },
  ussr_t34_85: { name:'T-34/85', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['mobile'],
    desc:'换装85毫米火炮的改进型,火力大幅提升。',
    story:'T-34/85装备85毫米火炮和三人炮塔,足以在正常交战距离上击穿德军虎式和豹式坦克的侧面装甲。' },
  ussr_su152: { name:'SU-152自行火炮', cost:5, atk:6, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    desc:'装备152毫米榴弹炮,一发就能掀翻虎式坦克的炮塔。',
    story:'SU-152装备152毫米榴弹炮,在库尔斯克会战中首次参战就表现出惊人威力,苏军士兵称它为“猎兽者”。' },
  ussr_guards_tank: { name:'近卫坦克军', cost:6, atk:5, hp:6, type:'unit', unitType:'land', rarity:'legendary', nation:'ussr',
    keywords:['rush'],
    desc:'苏军装甲部队的精华,在进攻中担任矛头。',
    story:'近卫坦克军是苏联红军最精锐的装甲部队,通常装备最新的T-34/85和IS-2坦克,从斯大林格勒一直打到柏林。' },
  ussr_ys2_122: { name:'122毫米榴弹炮', cost:3, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'苏军炮兵的主力火炮,以密集火力压制德军阵地。',
    story:'M-30 122毫米榴弹炮是苏联在二战中最重要的野战火炮之一,广泛装备于步兵师和炮兵旅。' },
  ussr_naval_infantry: { name:'海军步兵', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['rush'],
    desc:'“黑色死神”,从战舰上登陆的水兵,以勇猛著称。',
    story:'苏联海军步兵穿着标志性的黑色制服,被德军称为“黑色死神”。以凶猛的近战和白刃战著称。' },
  ussr_orden: { name:'红旗勋章', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'heal_hq', value:5 },
    desc:'作战令:点击我方总部,恢复 5 点生命。',
    story:'红旗勋章是苏联最早的军事勋章之一,授予在保卫祖国中表现英勇的个人或部队。' },
  ussr_defense: { name:'纵深防御', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'ussr',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:3 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 3 点。',
    story:'苏军在库尔斯克等防御作战中构建了纵深达数百公里的多层防线,有效消耗了德军的进攻锐气。' },
  ussr_t34_76: { name:'T-34/76', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['mobile'],
    desc:'战争前期的主力型号,倾斜装甲令德军震惊。',
    story:'T-34/76装备76毫米火炮,倾斜装甲设计令德军在1941年大为震惊,被迫加速研制新型坦克应对。' },
  ussr_t34_57: { name:'T-34/57', cost:4, atk:5, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['firststrike'],
    desc:'换装57毫米长身管火炮的“坦克猎手”。',
    story:'T-34/57装备57毫米ZiS-4长身管火炮,穿甲能力超过76毫米型号,专门用于对付德军重装甲目标。' },
  ussr_t60: { name:'T-60轻型坦克', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['mobile'],
    desc:'在莫斯科汽车厂紧急生产的轻型坦克。',
    story:'T-60轻型坦克在莫斯科汽车厂紧急投产,装备20毫米机关炮,虽然火力薄弱但在战争初期填补了装甲部队的空缺。' },
  ussr_t70: { name:'T-70轻型坦克', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['mobile'],
    desc:'T-60的改进型,装甲和火力有所提升。',
    story:'T-70装备45毫米火炮,装甲防护优于T-60,但单炮塔设计限制了作战效率,主要承担侦察和支援任务。' },
  ussr_bt7: { name:'BT-7快速坦克', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['mobile'],
    desc:'克里斯蒂悬挂的快速坦克,速度极快但装甲薄弱。',
    story:'BT-7采用克里斯蒂悬挂,公路时速可达72公里,是苏军战前的主要快速坦克,在1941年的边境战斗中大量损失。' },
  ussr_bt5: { name:'BT-5快速坦克', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['mobile'],
    desc:'BT系列的早期型号,曾参加西班牙内战。',
    story:'BT-5快速坦克曾出口到西班牙共和国,在西班牙内战中积累了宝贵的装甲作战经验。' },
  ussr_t26: { name:'T-26轻型坦克', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'战前苏军数量最多的轻型坦克。',
    story:'T-26轻型坦克总产量超过一万辆,是苏军战前装备最多的坦克,在1941年德军的闪击战中损失惨重。' },
  ussr_t28: { name:'T-28中型坦克', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'多炮塔设计的中型坦克,在冬季战争中首次参战。',
    story:'T-28中型坦克采用多炮塔设计,装备76毫米主炮,在1939至1940年的苏芬冬季战争中首次大规模参战。' },
  ussr_t35: { name:'T-35重型坦克', cost:5, atk:4, hp:6, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    desc:'五个炮塔的钢铁巨兽,宣传上的明星但实战表现不佳。',
    story:'T-35重型坦克有五个炮塔,是当时世界上最大的坦克之一。但机动性极差、机械故障频发,1941年大多在战斗中损毁或被遗弃。' },
  ussr_kv2: { name:'KV-2重型坦克', cost:5, atk:6, hp:7, type:'unit', unitType:'land', rarity:'epic', nation:'ussr',
    keywords:['guard'],
    desc:'装备152毫米榴弹炮的“街垒杀手”,高大笨重但火力恐怖。',
    story:'KV-2装备152毫米榴弹炮,巨大的炮塔令其重心过高,但一发炮弹就能摧毁德军任何坦克。1941年曾在拉塞尼艾独自阻挡德军一天。' },
  ussr_kv85: { name:'KV-85重型坦克', cost:5, atk:5, hp:6, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['guard'],
    desc:'换装85毫米火炮的KV系列改进型。',
    story:'KV-85是KV-1S换装85毫米火炮的过渡型号,火力大幅提升,为后续IS系列坦克的研制积累了经验。' },
  ussr_is3: { name:'IS-3重型坦克', cost:7, atk:7, hp:8, type:'unit', unitType:'land', rarity:'legendary', nation:'ussr',
    keywords:['guard'],
    desc:'楔形车首和半圆形炮塔,战争末期最先进的苏联重型坦克。',
    story:'IS-3于1945年5月投入柏林前线,装备122毫米火炮和楔形装甲,其外形设计影响了战后苏联坦克的发展方向。' },
  ussr_isu122: { name:'ISU-122自行火炮', cost:5, atk:6, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'以IS-2为底盘的122毫米自行火炮。',
    story:'ISU-122装备122毫米A-19火炮,火力强悍,主要用于反坦克和攻坚作战,是苏军重要的自行火炮。' },
  ussr_isu152: { name:'ISU-152自行火炮', cost:6, atk:7, hp:5, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    desc:'“猎兽者”的后继型号,152毫米榴弹炮能掀翻任何德军坦克。',
    story:'ISU-152以IS-2重型坦克为底盘,装备152毫米榴弹炮,柏林战役中大量用于摧毁德军街垒工事。' },
  ussr_su76: { name:'SU-76自行火炮', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'“裸体苏卡”,敞开式战斗室的轻型自行火炮。',
    story:'SU-76以T-70为底盘,装备76毫米火炮,因防护薄弱被士兵戏称为“裸体苏卡”,但产量大、机动性好。' },
  ussr_su85: { name:'SU-85坦克歼击车', cost:4, atk:5, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['firststrike'],
    desc:'装备85毫米火炮的坦克歼击车。',
    story:'SU-85以T-34为底盘,装备85毫米D-5T火炮,专门用于对付德军的虎式和豹式坦克。' },
  ussr_su100: { name:'SU-100坦克歼击车', cost:5, atk:6, hp:4, type:'unit', unitType:'land', rarity:'epic', nation:'ussr',
    keywords:['firststrike'],
    desc:'100毫米火炮,二战中最优秀的坦克歼击车之一。',
    story:'SU-100装备100毫米D-10S火炮,火力强悍,被认为能与德军虎王坦克正面抗衡,在战争后期大量服役。' },
  ussr_su122: { name:'SU-122自行火炮', cost:4, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'装备122毫米榴弹炮的突击炮。',
    story:'SU-122以T-34为底盘,装备122毫米榴弹炮,主要用于近距离摧毁德军工事和火力点。' },
  ussr_t44: { name:'T-44中型坦克', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['mobile'],
    desc:'T-34的后继型号,采用横向发动机布局。',
    story:'T-44于1944年投产,采用横向发动机布局和 torsion bar 悬挂,改善了T-34的诸多缺陷,但未及大规模参战。' },
  ussr_guards_tank_brigade: { name:'近卫坦克旅', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'ussr',
    keywords:['rush'],
    desc:'突击作战中的装甲矛头,通常编有重型坦克。',
    story:'苏军近卫坦克旅通常在关键突破方向投入,装备T-34/85和IS-2等最新型号,是装甲部队中的精锐。' },
  ussr_zis3: { name:'76毫米ZiS-3', cost:3, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'“万能炮”,既能反坦克又能支援步兵。',
    story:'ZiS-3 76毫米火炮是苏军在二战中产量最大的火炮,既能执行反坦克任务,也能作为步兵支援炮使用。' },
  ussr_ml20: { name:'152毫米榴弹炮', cost:4, atk:5, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'“钢铁暴雨”,能摧毁德军坚固工事。',
    story:'ML-20 152毫米榴弹炮是苏军最重要的重型火炮之一,在攻坚作战中发挥巨大作用,也被用于ISU-152自行火炮。' },
  ussr_b4: { name:'203毫米榴弹炮', cost:6, atk:7, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    desc:'“斯大林大锤”,专为轰塌混凝土工事而生。',
    story:'B-4 203毫米榴弹炮是苏军威力最大的野战火炮,主要用于轰击德军坚固筑垒和城市街垒,其履带式炮架设计独特。' },
  ussr_45mm_at: { name:'45毫米反坦克炮', cost:2, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'“再见,祖国”,苏军步兵师的标准反坦克炮。',
    story:'45毫米反坦克炮是苏军战争初期的标准反坦克武器,因射击后炮手常需暴露自身,被戏称为“再见,祖国”。' },
  ussr_zis2: { name:'57毫米反坦克炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    keywords:['firststrike'],
    desc:'“游猎者”,穿甲能力出色的反坦克炮。',
    story:'ZiS-2 57毫米反坦克炮穿甲能力极强,1941年一度停产,1943年因德军虎式坦克大量出现而恢复生产。' },
  ussr_37mm_aa: { name:'37毫米高射炮', cost:2, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'低空防空的利器,也能平射反步兵。',
    story:'61-K 37毫米高射炮是苏军主要的低空防空武器,也能平射攻击地面目标。' },
  ussr_85mm_aa: { name:'85毫米高射炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'中高空防空炮,也常被用于反坦克。',
    story:'52-K 85毫米高射炮是苏军重要的中高空防空武器,在反坦克作战中也表现出色。' },
  ussr_120mm_mortar: { name:'120毫米迫击炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'威力最大的步兵支援迫击炮。',
    story:'120毫米迫击炮是苏军在二战中使用的最大口径步兵迫击炮,威力强大,德军也仿制了该炮。' },
  ussr_bm8: { name:'BM-8火箭炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'82毫米火箭炮,主要用于近距离火力压制。',
    story:'BM-8是一种轻型多管火箭炮,使用82毫米火箭弹,通常安装在卡车或坦克底盘上。' },
  ussr_bm31: { name:'BM-31火箭炮', cost:5, atk:6, hp:2, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    desc:'300毫米重型火箭炮,齐射时天崩地裂。',
    story:'BM-31装备300毫米重型火箭弹,一发弹头重量超过70公斤,齐射时能造成大面积毁灭。' },
  ussr_yak9: { name:'雅克-9', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'产量最大的雅克系列战斗机,多用途性强。',
    story:'雅克-9是雅克系列中产量最大的型号,有多种改型,可执行空战、对地攻击和侦察等多种任务。' },
  ussr_yak3: { name:'雅克-3', cost:5, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    keywords:['mobile'],
    desc:'低空格斗的王者,轻巧灵活。',
    story:'雅克-3是二战中最轻的战斗机之一,低空机动性极为出色,德军飞行员被要求避免与其低空缠斗。' },
  ussr_la5: { name:'拉-5', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'使用星型发动机,斯大林格勒上空的守护者。',
    story:'拉-5换装星型发动机后性能大幅提升,在库班空战和库尔斯克会战中表现出色,成为苏军主力战斗机之一。' },
  ussr_la7: { name:'拉-7', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    keywords:['mobile'],
    desc:'拉系列终极型号,击落德军喷气机的英雄座机。',
    story:'拉-7是拉系列的最后改型,性能优异。苏联王牌飞行员阔日杜布驾驶拉-7击落了包括Me 262喷气机在内的多架敌机。' },
  ussr_mig3: { name:'米格-3', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'高空截击机,但低空性能不佳。',
    story:'米格-3设计用于高空截击,但战争初期苏德空战多在中低空进行,其性能优势难以发挥。' },
  ussr_lagg3: { name:'拉格-3', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'木质结构战斗机,性能中庸但产量大。',
    story:'拉格-3采用木质结构以节省战略物资,性能不及德军Bf 109,但在战争初期填补了苏军战斗机的空缺。' },
  ussr_pe2: { name:'佩-2', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    keywords:['rush'],
    desc:'快速俯冲轰炸机,速度超过许多战斗机。',
    story:'佩-2是苏军优秀的俯冲轰炸机,速度极快,许多德军战斗机都难以追上。它执行了大量精确轰炸任务。' },
  ussr_tu2: { name:'图-2', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'双发中型轰炸机,火力与载弹量兼备。',
    story:'图-2是苏军在二战中最优秀的中型轰炸机,装备多门机炮,载弹量大,也具备一定的自卫能力。' },
  ussr_il4: { name:'伊尔-4', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'双发远程轰炸机,曾轰炸柏林。',
    story:'伊尔-4是苏军的双发远程轰炸机,1941年8月曾从波罗的海岛屿起飞轰炸柏林,作为对德军空袭莫斯科的回应。' },
  ussr_pe8: { name:'佩-8', cost:6, atk:6, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    desc:'四发重型轰炸机,航程远载弹量大。',
    story:'佩-8是苏军唯一批量生产的四发重型轰炸机,曾执行轰炸柏林等远程任务,但产量有限。' },
  ussr_yak1: { name:'雅克-1', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'战争初期的主力战斗机。',
    story:'雅克-1是雅克系列的首款量产型号,性能均衡,在战争初期是苏军的重要战斗机。' },
  ussr_po2: { name:'波-2', cost:2, atk:2, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    keywords:['stealth'],
    desc:'“缝纫机”,夜间骚扰轰炸的木质飞机。',
    story:'波-2是初级教练机改装的夜间轰炸机,飞行时发动机声音像缝纫机。由女飞行员组成的第588夜间轰炸机团驾驶波-2袭击德军营地,德军称之为“夜女巫”。' },
  ussr_il10: { name:'伊尔-10', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    keywords:['rush'],
    desc:'伊尔-2的后继型号,速度更快、火力更强。',
    story:'伊尔-10是伊尔-2的后继型号,改进了气动外形和火力配置,但服役时战争已近尾声。' },
  ussr_lagg5: { name:'拉-5FN', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'拉-5的改进型,装备直接喷射发动机。',
    story:'拉-5FN换装直接喷射发动机,性能进一步提升,是苏军在战争后期的重要战斗机之一。' },
  ussr_yak7: { name:'雅克-7', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'雅克-1的双座改进型,也用作教练机。',
    story:'雅克-7是雅克-1的双座改进型,可用于战斗和训练,一些型号还被改装为炮兵校射机。' },
  ussr_rail_partisan: { name:'铁路游击队', cost:3, atk:4, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['stealth'],
    desc:'在德军后方破坏铁路线的游击队。',
    story:'1943年苏联游击队发动“铁路战争”,一夜之间破坏数千段铁轨,严重迟滞德军调动。' },
  ussr_recon_team: { name:'敌后侦察队', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    keywords:['stealth'],
    desc:'深入敌后提供精确情报的小分队。',
    story:'苏军敌后侦察队深入德军纵深,监视部队调动和补给情况,为苏军指挥部提供关键情报。' },
  ussr_guerrilla_hq: { name:'游击队指挥部', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +1/+1。',
    story:'苏军在德军后方建立游击队指挥部,统一协调各地游击队的行动,破坏德军补给线和通信网络。' },
  ussr_sniper_squad: { name:'狙击手小队', cost:3, atk:5, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'ussr',
    keywords:['stealth'],
    desc:'两人一组,一人射击一人观察,专猎德军军官。',
    story:'苏军狙击手通常两人一组行动,一人负责射击,一人负责观察和警戒,优先击杀德军军官和通信兵。' },
  ussr_at_dogs: { name:'反坦克狗', cost:1, atk:3, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'ussr',
    desc:'背负炸药冲向德军坦克的自杀式反坦克手段。',
    story:'苏军曾训练狗背负炸药钻入坦克底部引爆,但实际效果有限,许多狗因被训练时接触的是苏军坦克的声音而误伤己方。' },
  ussr_black_sea_fleet: { name:'黑海舰队', cost:4, atk:4, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'支援塞瓦斯托波尔和敖德萨的海上力量。',
    story:'黑海舰队在二战中支援了塞瓦斯托波尔和敖德萨的防御作战,也执行了多次两栖登陆任务。' },
  ussr_baltic_fleet: { name:'波罗的海舰队', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'ussr',
    desc:'被困芬兰湾的舰队,仍以舰炮支援陆军。',
    story:'波罗的海舰队在战争初期撤至喀琅施塔得,被德军水雷封锁,但仍以舰炮火力支援列宁格勒保卫战。' },
  ussr_north_fleet: { name:'北方舰队', cost:3, atk:3, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    desc:'保护北极航线的海军力量。',
    story:'北方舰队负责保护盟国经北极航线运往苏联的物资,与德军潜艇和飞机作战。' },
  ussr_kirov: { name:'基洛夫号巡洋舰', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'epic', nation:'ussr',
    desc:'波罗的海舰队的旗舰,以炮火支援列宁格勒。',
    story:'基洛夫号巡洋舰是苏联海军最著名的军舰之一,列宁格勒围城期间,该舰以主炮支援城内守军。' },
  ussr_submarine: { name:'潜艇部队', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'ussr',
    keywords:['stealth'],
    desc:'在波罗的海和黑海猎杀德军运输船。',
    story:'苏联潜艇部队在波罗的海和黑海作战,击沉了多艘德军运输船,但自身也付出了惨重代价。' },
  ussr_deep_ops: { name:'大纵深作战', cost:5, atk:0, hp:0, type:'command', rarity:'epic', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +2/+2。',
    story:'“大纵深作战”是苏军在1930年代提出的军事理论,强调以坦克和机械化部队突破敌防线后向纵深扩张。这一理论在战争后期被成功运用。' },
  ussr_artillery_prep: { name:'炮兵准备', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:4 },
    desc:'作战令:点击敌方单位或敌方总部,造成 4 点伤害。',
    story:'苏军在大规模进攻前通常进行长时间炮火准备,以密集炮击摧毁德军防线,为步兵和坦克开辟通路。' },
  ussr_shock_group_cmd: { name:'突击队形', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:3, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +3/+0。',
    story:'苏军在进攻时通常组成多个梯队的突击队形,第一梯队突破德军防线后,后续梯队立即扩张战果。' },
  ussr_at_defense: { name:'反坦克防御', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'ussr',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:3 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 3 点伤害。',
    story:'苏军在库尔斯克会战中构筑了纵深达数百公里的反坦克防御体系,包括反坦克炮、地雷和反坦克壕。' },
  ussr_scorched_retreat: { name:'焦土撤退', cost:2, atk:0, hp:0, type:'command', rarity:'common', nation:'ussr',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:3 },
    desc:'作战令:点击敌方单位或敌方总部,造成 3 点伤害。',
    story:'苏军在1941年撤退时实施焦土政策,破坏粮食、铁路和工业设施,以迟滞德军推进。' },
  ussr_winter_counter: { name:'冬季反攻', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +2/+1。',
    story:'1941年12月,苏军在莫斯科城下发动冬季反攻,将德军击退数百公里,打破了德军不可战胜的神话。' },
  ussr_night_attack: { name:'夜战突击', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:5 },
    desc:'作战令:点击敌方单位或敌方总部,造成 5 点伤害。',
    story:'苏军擅长夜战,常在夜间发动突然袭击,利用德军夜间防御薄弱的弱点取得战果。' },
  ussr_political_mob: { name:'政治动员', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'heal_hq', value:6 },
    desc:'作战令:点击我方总部,恢复 6 点生命。',
    story:'苏军通过政治动员激励士兵保卫祖国,政治委员在部队中发挥重要作用,许多士兵在战斗中喊出“为了祖国”的口号。' },
  ussr_war_production: { name:'战时生产', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'heal_hq', value:8 },
    desc:'作战令:点击我方总部,恢复 8 点生命。',
    story:'苏军在战争期间将大量工厂东迁至乌拉尔山以东,生产能力迅速恢复并超越德国,为最终胜利奠定了物质基础。' },
  ussr_tank_ambush: { name:'坦克伏击', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'ussr',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 4 点伤害。',
    story:'苏军坦克部队经常利用地形设伏,将坦克隐蔽在树林或高地后方,待德军进入射程后突然开火。' },
  ussr_rocket_salvo: { name:'火箭炮齐射', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'ussr',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:6 },
    desc:'作战令:点击敌方单位或敌方总部,造成 6 点伤害。',
    story:'苏军喀秋莎火箭炮齐射时能在数秒内倾泻大量火箭弹,覆盖整个区域,德军士兵称之为“斯大林管风琴”。' },
  ussr_order_227: { name:'227号命令', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +2/+0。',
    story:'1942年7月,斯大林签署第227号命令,要求苏军“一步也不后退”。这道命令在斯大林格勒战役中极大鼓舞了守军士气。' },
  ussr_deep_battle: { name:'纵深突破', cost:4, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +1/+2。',
    story:'苏军在战争后期发展出成熟的纵深突破战术,以坦克军和机械化军快速突入德军防线纵深,合围德军重兵集团。' },
  ussr_counter_battery: { name:'反炮兵作战', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'ussr',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:4 },
    desc:'作战令:点击敌方单位或敌方总部,造成 4 点伤害。',
    story:'苏军通过航空侦察和测向技术定位德军炮兵阵地,然后以密集火力实施反炮兵打击。' },
  ussr_spetsnaz: { name:'特种作战', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'ussr',
    trigger:'enemy_deploy', effect:{ type:'damage_hq', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对敌方总部造成 4 点伤害。',
    story:'苏军特种部队深入德军后方,破坏指挥所、通信枢纽和补给基地,为正面战场创造有利条件。' },
  ussr_ambush_counter: { name:'诱敌伏击', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'ussr',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:5 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 5 点伤害。',
    story:'苏军常以少量部队诱敌深入,然后在预设阵地以密集火力打击德军,这种战术在防御作战中屡试不爽。' },
  ussr_scorched: { name:'坚壁清野', cost:2, atk:0, hp:0, type:'counter', rarity:'common', nation:'ussr',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:4 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 4 点。',
    story:'苏军撤退时带走或销毁一切可能被德军利用的物资,使德军在占领区难以获得补给,有效迟滞其推进。' },
  ussr_tank_ace: { name:'王牌坦克手', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'ussr',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 4 点伤害。',
    story:'苏军涌现出许多王牌坦克手,如拉夫里年科,在1941年驾驶KV-1坦克击毁多辆德军坦克。' },
  ussr_defensive_line: { name:'防御工事', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'ussr',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:3 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 3 点。',
    story:'苏军在重要城市和战略要地构筑多层防御工事,包括反坦克壕、地雷场和火力点,有效迟滞德军进攻。' },
  ussr_guerrilla_raid: { name:'游击队突袭', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'ussr',
    trigger:'enemy_deploy', effect:{ type:'damage_hq', value:3 },
    desc:'应变:布下后,敌方部署单位时触发,对敌方总部造成 3 点伤害。',
    story:'苏联游击队在白俄罗斯、乌克兰等地频繁袭击德军补给线和指挥所,据估计共造成德军数十万人伤亡。' },
    japan_ha_go: { name:'九五式轻型坦克', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    keywords:['mobile'],
    desc:'日军轻型坦克的主力,在中国和东南亚战场上广泛使用。',
    story:'九五式轻型坦克“哈号”是日本在1935年定型的主力轻型坦克,总产量超过2000辆。' },
  japan_zero: { name:'零式战斗机', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['mobile'],
    desc:'战争初期统治太平洋天空的传奇战斗机。',
    story:'零式战斗机以惊人的机动性和超长航程著称,在战争初期几乎无敌于太平洋上空。' },
  japan_yamato: { name:'大和号战列舰', cost:7, atk:6, hp:8, type:'unit', unitType:'ranged', rarity:'legendary', nation:'japan',
    keywords:['guard'],
    desc:'人类历史上最大的战列舰,象征日本海军的荣光。',
    story:'大和号装备九门460毫米主炮,排水量超过七万吨。1945年4月在冲绳战役中被美军舰载机群击沉。' },
  japan_imperial_guard: { name:'近卫师团', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    keywords:['rush'],
    desc:'天皇的直属部队,日军中最精锐的师团之一。',
    story:'近卫师团直接隶属于天皇,在二战中参加了马来亚战役和新加坡战役。' },
  japan_kamikaze: { name:'神风特攻', cost:3, atk:4, hp:1, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['rush'],
    desc:'以生命为代价的自杀式攻击,给美军舰队造成了巨大心理冲击。',
    story:'神风特攻首次使用于1944年莱特湾海战,在冲绳战役中达到高峰,击沉了数十艘美军舰艇。' },
  japan_type97: { name:'九七式中型坦克', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'日军装甲部队的中坚,在中国和太平洋岛屿上作战。',
    story:'九七式中型坦克是日本在二战中生产数量最多的坦克,装备57毫米短管火炮。' },
  japan_battleship_yamato: { name:'海军陆战队', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'日本海军的精锐地面部队,负责岛屿防御和两栖作战。',
    story:'日本海军陆战队(特别陆战队)在太平洋岛屿的防御战中表现出顽强的战斗力,尤其擅长夜战和近战。' },
  japan_aki_division: { name:'岚兵团', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    keywords:['rush'],
    desc:'以“岚”为通称号的精锐师团,在缅甸和太平洋战场上作战。',
    story:'岚兵团是日本帝国陆军第16师团的通称号,参加了英帕尔战役和冲绳战役。' },
  japan_kawanishi: { name:'川西H8K', cost:5, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    desc:'远程水上飞机,执行海上巡逻和侦察任务。',
    story:'川西H8K“二式飞行艇”是当时世界上最先进的水上飞机之一,拥有超长的航程和良好的海上起降能力。' },
  japan_yongsan: { name:'龙山联队', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'第20师团的主力联队,在朝鲜和新几内亚作战。',
    story:'龙山联队随第20师团被调往新几内亚战场,在恶劣的丛林环境中遭受严重损失。' },
  japan_imperial_navy: { name:'海军航空兵', cost:3, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'日本海军的精英飞行员,在太平洋战争初期战果辉煌。',
    story:'日本海军航空兵在战争初期拥有世界上最优秀的飞行员之一,在珍珠港、印度洋和珊瑚海等战役中取得辉煌战果。' },
  japan_midway: { name:'中途岛', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'heal_hq', value:6 },
    desc:'作战令:点击我方总部,恢复 6 点生命。',
    story:'中途岛海战是太平洋战争的转折点。短短五分钟内,美军舰载机击沉日军四艘主力航母。' },
  japan_bushido: { name:'武士道精神', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +2/+0。',
    story:'武士道精神是日本军国主义的核心意识形态,强调忠诚、荣誉和为国家牺牲。' },
  japan_pearl_harbor: { name:'偷袭珍珠港', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'japan',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:6 },
    desc:'作战令:点击敌方单位或敌方总部,造成 6 点伤害。',
    story:'1941年12月7日,日本海军出动六艘航母突袭珍珠港,将美国彻底拖入了战争。' },
  japan_island_defense: { name:'岛屿防御', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:0, hp:3 },
    desc:'作战令:点击我方总部,全体单位 +0/+3。',
    story:'在塔拉瓦、硫磺岛和冲绳等地,日军利用复杂地形和密集火力点,给登陆的美军造成巨大伤亡。' },
  japan_type4: { name:'四式战斗机', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'日本陆军航空兵的中坚战斗机,与美军争夺制空权。',
    story:'四式战斗机“疾风”是日本陆军在二战中最优秀的战斗机之一,由中岛飞机公司研制。' },
  japan_convoy: { name:'运输船队', cost:2, atk:1, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'维持岛屿补给的运输船,常常成为美军潜艇的猎物。',
    story:'日本海军对商船护航的重视不足,导致大量运输船被美军潜艇击沉,严重削弱了其战争能力。' },
  japan_bataan: { name:'巴丹死亡行军', cost:3, atk:4, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'在菲律宾战役中迫使盟军战俘进行残酷的行军。',
    story:'1942年日军在攻占巴丹半岛后,迫使约7.5万名美菲战俘在烈日下徒步行走约100公里。' },
  japan_kaiten: { name:'回天鱼雷', cost:3, atk:4, hp:1, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    keywords:['firststrike'],
    desc:'由人操纵向目标的鱼雷,以生命换取一击。',
    story:'回天鱼雷由潜艇携带至目标附近发射,操作员在接近敌舰时手动控制方向,最终撞击目标。' },
  japan_air_defense: { name:'本土防空', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'japan',
    trigger:'enemy_deploy', effect:{ type:'damage_hq', value:3 },
    desc:'应变:布下后,敌方部署单位时触发,对敌方总部造成 3 点伤害。',
    story:'战争后期美军对日本本土展开大规模轰炸,日军以高射炮和战斗机拦截,但未能阻止轰炸。' },
  japan_2nd_division: { name:'第2师团', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'“仙台师团”,关东军的主力,在中国东北和太平洋战场作战。',
    story:'第2师团通称号“勇”,因士兵多来自仙台地区而得名“仙台师团”。二战中参加了马来亚战役、瓜岛战役和缅甸战场。' },
  japan_3rd_division: { name:'第3师团', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'“名古屋师团”,日军常备师团之一。',
    story:'第3师团通称号“幸”,是日军最早的常备师团之一,参加了中国战场多场战役及菲律宾作战。' },
  japan_5th_division: { name:'第5师团', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'“广岛师团”,以凶悍善战著称。',
    story:'第5师团通称号“鲤”,因士兵多来自广岛地区而得名。参加了马来亚战役、新加坡战役及太平洋岛屿作战。' },
  japan_6th_division: { name:'第6师团', cost:4, atk:5, hp:4, type:'unit', unitType:'land', rarity:'epic', nation:'japan',
    keywords:['rush'],
    desc:'“熊本师团”,南京大屠杀的主力部队之一。',
    story:'第6师团通称号“明”,是日军最凶悍的师团之一,在南京大屠杀中犯下严重暴行。后在布干维尔岛被美军重创。' },
  japan_18th_division: { name:'第18师团', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'japan',
    keywords:['rush'],
    desc:'“菊兵团”,在缅甸战场与中国远征军激战。',
    story:'第18师团通称号“菊”,是日军在缅甸战场的主力部队之一,在胡康河谷和密支那等地与中国驻印军和美军展开激战。' },
  japan_33rd_division: { name:'第33师团', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'“弓兵团”,在缅甸与中国远征军多次交战。',
    story:'第33师团通称号“弓”,在缅甸战场担任重要作战任务,参加了同古战役和英帕尔作战。' },
  japan_56th_division: { name:'第56师团', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'japan',
    keywords:['guard'],
    desc:'“龙兵团”,在缅甸战场长期与中国军队对峙。',
    story:'第56师团通称号“龙”,是日军在缅甸战场的重要部队,参加了滇西反攻作战中的多次防守战。' },
  japan_1st_division: { name:'第1师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“东京师团”,日军最古老的常备师团。',
    story:'第1师团通称号“旭”,是日军最早建立的师团之一,长期驻守中国东北和菲律宾。' },
  japan_4th_division: { name:'第4师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“大阪师团”,以精于经商闻名,但作战能力不弱。',
    story:'第4师团通称号“淀”,因士兵多来自大阪地区而得名。虽然以“不爱打仗”出名,但在菲律宾战场上同样表现出顽强的作战能力。' },
  japan_9th_division: { name:'第9师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“金泽师团”,在冲绳战役中死守首里防线。',
    story:'第9师团通称号“武”,在冲绳战役中担任首里防线的坚守任务,与美军展开激烈的拉锯战。' },
  japan_10th_division: { name:'第10师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“姬路师团”,在中国战场长期作战。',
    story:'第10师团通称号“铁”,是日军在中国战场的重要力量,参加了武汉会战和长沙会战等战役。' },
  japan_11th_division: { name:'第11师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“善通寺师团”,参加过淞沪会战。',
    story:'第11师团通称号“锦”,在淞沪会战中担任日军主力,后调往太平洋战场。' },
  japan_12th_division: { name:'第12师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“久留米师团”,在中国战场执行过多项任务。',
    story:'第12师团通称号“剑”,长期在中国战场作战,参加了长沙会战等一系列战役。' },
  japan_14th_division: { name:'第14师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“宇都宫师团”,在帕劳群岛顽强抵抗美军。',
    story:'第14师团通称号“照”,在帕劳群岛的贝里琉岛战役中坚守阵地,给美军造成重大伤亡。' },
  japan_16th_division: { name:'第16师团', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    keywords:['rush'],
    desc:'“中岛师团”,参加了南京大屠杀。',
    story:'第16师团通称号“中”,是参与南京大屠杀的主力部队之一。后调往莱特岛,几乎全军覆没。' },
  japan_19th_division: { name:'第19师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“罗南师团”,驻守朝鲜北部和菲律宾。',
    story:'第19师团通称号“虎”,长期驻守朝鲜北部,后在菲律宾吕宋岛作战。' },
  japan_20th_division: { name:'第20师团', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'“龙山师团”,在新几内亚丛林中损失惨重。',
    story:'第20师团通称号“朝”,被调往新几内亚战场,在恶劣的丛林环境中遭受严重损失,几乎全军覆没。' },
  japan_1st_marine_div: { name:'第1海军陆战师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'日本海军所属的精锐地面部队。',
    story:'日本海军陆战队在太平洋岛屿防御战中表现出顽强的战斗力,尤其擅长夜战和近战。' },
  japan_2nd_marine_div: { name:'第2海军陆战师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'海军陆战队的精锐部队,守卫塔拉瓦和塞班。',
    story:'第2海军陆战队在塔拉瓦环礁和塞班岛防御战中作战顽强,几乎全军覆没。' },
  japan_3rd_marine_div: { name:'第3海军陆战师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'守卫硫磺岛的日军精锐部队。',
    story:'第3海军陆战师在硫磺岛战役中依托地下工事顽强抵抗,给登陆的美军造成重大伤亡。' },
  japan_paratrooper: { name:'伞兵部队', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    keywords:['rush'],
    desc:'日军空降部队,曾参与菲律宾和印尼空降作战。',
    story:'日本海军和陆军的空降部队在战争初期参加了苏拉威西和巨港空降作战,取得了一定的战果。' },
  japan_special_naval: { name:'特别陆战队', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    keywords:['stealth'],
    desc:'海军陆战队的精锐单位,擅长夜袭。',
    story:'特别陆战队是日本海军的精锐地面部队,在瓜岛、塔拉瓦等战役中表现出顽强的战斗力。' },
  japan_kempeitai: { name:'宪兵队', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'日本军队的军事警察,负责占领区的控制。',
    story:'宪兵队(宪兵)在占领区执行残酷的统治,参与了多起战争暴行,战后被列为战争犯罪组织。' },
  japan_kempetai_officer: { name:'宪兵军官', cost:2, atk:0, hp:0, type:'command', rarity:'common', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +1/+1。',
    story:'宪兵军官在占领区负责控制和镇压,以严酷手段维持占领秩序,在占领区犯下了大量暴行。' },
  japan_sniper_team: { name:'狙击小组', cost:2, atk:3, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    keywords:['stealth'],
    desc:'隐藏在树上或灌木丛中的狙击手,射杀盟军军官。',
    story:'日军狙击手常隐藏在树上或地面掩体中,瞄准指挥官和通信兵,在太平洋战场上给美军造成不小的威胁。' },
  japan_bicycle_infantry: { name:'自行车步兵', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    keywords:['mobile'],
    desc:'骑着自行车快速推进的步兵部队。',
    story:'日军在马来亚战役中使用自行车部队快速穿越丛林,以惊人的速度南进,令英军措手不及。' },
  japan_banzai: { name:'万岁冲锋', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:3, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +3/+0。',
    story:'“万岁冲锋”是日军在战局不利时发动的自杀式攻击,士兵高呼“天皇陛下万岁”,向敌军阵地发起冲锋,通常以全军覆没告终。' },
  japan_bamboo_spear: { name:'竹枪民兵', cost:1, atk:1, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'装备简陋的民间武装,在本土决战准备中被动员。',
    story:'战争末期,日本政府号召全民“玉碎”,大量平民被动员起来准备本土决战,许多人只装备竹枪和简陋武器。' },
  japan_hitler_youth: { name:'少年兵', cost:1, atk:1, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'战争末期被征召的年轻士兵。',
    story:'战争末期日军兵员严重不足,大量少年被提前征召入伍,在冲绳战役中大量伤亡。' },
  japan_naval_landing: { name:'海军登陆队', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    keywords:['rush'],
    desc:'专门执行两栖登陆作战的海军部队。',
    story:'日本海军登陆队(吴海军特别陆战队等)在太平洋战争中执行了大量两栖登陆和岛屿防御任务。' },
  japan_engineer_regiment: { name:'工兵联队', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'负责修筑工事和排除障碍的工兵部队。',
    story:'日军工兵在太平洋岛屿上构筑了大量地下工事和坑道,这些工事在防御战中发挥了重要作用。' },
  japan_signal_corps: { name:'通信联队', cost:2, atk:1, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'保障指挥通信的部队。',
    story:'通信部队在太平洋岛屿作战中面临美军强大的电子干扰,通信经常中断,严重影响了日军的协同作战能力。' },
  japan_medic: { name:'卫生兵', cost:1, atk:1, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'在战场上抢救伤员,但日军医疗资源严重不足。',
    story:'日军在太平洋岛屿上的医疗资源严重不足,大量伤员因缺乏药品和医疗条件而死亡。' },
  japan_tank_killer: { name:'对坦克格斗兵', cost:2, atk:3, hp:1, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    keywords:['firststrike'],
    desc:'携带炸药或磁性雷近身攻击坦克的士兵。',
    story:'日军在太平洋岛屿防御中采用“肉弹攻击”战术,士兵携带炸药包或磁性反坦克雷靠近美军坦克引爆。' },
  japan_bunker_defender: { name:'地堡守备兵', cost:2, atk:2, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    keywords:['guard'],
    desc:'坚守地堡的士兵,战斗到最后一人。',
    story:'日军在太平洋岛屿上依托坚固的地下工事顽强抵抗,即使被火焰喷射器或炸药包攻击也不投降,往往战至最后一人。' },
  japan_mountain_gun: { name:'九二式步兵炮', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'轻便的步兵支援火炮,可由骡马拖曳。',
    story:'九二式步兵炮是日军步兵联队的标准支援火炮,重量轻、便于机动,适合在丛林和山地作战。' },
  japan_37mm_at: { name:'37毫米反坦克炮', cost:2, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'日军主要的反坦克火炮,威力有限。',
    story:'日军37毫米反坦克炮在战争初期能对付盟军轻型坦克,但面对谢尔曼坦克时穿透力明显不足。' },
  japan_47mm_at: { name:'47毫米反坦克炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'日军改进型反坦克炮,能击穿谢尔曼坦克的侧装甲。',
    story:'一式47毫米反坦克炮是日军在战争后期的主要反坦克武器,能击穿谢尔曼坦克的侧后装甲。' },
  japan_70mm_howitzer: { name:'70毫米榴弹炮', cost:3, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'轻型支援火炮,广泛用于岛屿作战。',
    story:'九二式70毫米步兵炮(大队炮)是日军大队级的支援火炮,重量轻、便于隐蔽,在太平洋岛屿防御中发挥了一定的作用。' },
  japan_75mm_mountain: { name:'九四式山炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'可拆解运输的山地火炮。',
    story:'九四式75毫米山炮可拆解成多个部分由骡马或士兵搬运,适合在丛林和山地环境中作战。' },
  japan_105mm_howitzer: { name:'105毫米榴弹炮', cost:4, atk:5, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'日军师团级的重型支援火炮。',
    story:'九一式105毫米榴弹炮是日军师团级炮兵的主力火炮,但由于运输困难,在太平洋岛屿上难以有效部署。' },
  japan_150mm_howitzer: { name:'150毫米榴弹炮', cost:5, atk:6, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'日军威力最大的野战火炮之一。',
    story:'九六式150毫米榴弹炮是日军重要的重型火炮,但由于运输和部署困难,在太平洋岛屿战场使用有限。' },
  japan_320mm_mortar: { name:'320毫米迫击炮', cost:5, atk:6, hp:2, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    desc:'口径极大的臼炮,用于轰击美军机场。',
    story:'日军在硫磺岛部署了320毫米迫击炮,用于轰击美军机场,但由于弹药有限,未能发挥决定性作用。' },
  japan_type96_mg: { name:'九六式轻机枪', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'日军步兵的轻型机枪,配刺刀可近战。',
    story:'九六式轻机枪是日军步兵的主要支援武器之一,其独特之处在于可以安装刺刀,体现了日军重视白刃战的特点。' },
  japan_type92_mg: { name:'九二式重机枪', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'日军重机枪,以射击精度著称。',
    story:'九二式重机枪采用保弹板供弹,射击精度较高,但射速较慢,是日军步兵联队的重要支援火力。' },
  japan_type99_mg: { name:'九九式轻机枪', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'日军后期使用的轻机枪,口径更大。',
    story:'九九式轻机枪使用7.7毫米弹药,射程和威力均优于九六式,但产量有限。' },
  japan_type99_rifle: { name:'九九式步枪', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'日军后期的主力步枪,口径7.7毫米。',
    story:'九九式短步枪是日军在战争后期装备的主力步枪,使用7.7毫米弹药,威力大于三八式。' },
  japan_ariskaka: { name:'有坂步枪', cost:1, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'三八式步枪,日军步兵的标志性武器。',
    story:'三八式步枪(有坂步枪)以射击精度和可靠性著称,是日军步兵在二战中的主要步枪,使用6.5毫米弹药。' },
  japan_knee_mortar: { name:'八九式掷弹筒', cost:2, atk:2, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'单兵使用的轻型迫击炮。',
    story:'八九式掷弹筒是日军步兵小队级的支援武器,重量轻、便于携带,能发射高爆弹和榴弹。' },
  japan_kamikaze_plane: { name:'神风特攻机', cost:4, atk:6, hp:1, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['rush'],
    desc:'装满炸药的飞机,以生命为代价撞击敌舰。',
    story:'神风特攻队驾驶装满炸药的飞机撞击美军舰船,在冲绳战役中击沉了多艘美军舰艇,给美军造成巨大的心理压力。' },
  japan_ohka: { name:'樱花特攻机', cost:4, atk:7, hp:1, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['rush'],
    desc:'由轰炸机携带的火箭推进自杀式飞机。',
    story:'“樱花”是一种由一式陆攻轰炸机携带的火箭推进自杀式飞机,速度极快难以拦截,但只能在有限距离内使用。' },
  japan_kaiten_sub: { name:'回天搭载潜艇', cost:4, atk:3, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    keywords:['stealth'],
    desc:'搭载人操鱼雷的潜艇,用于攻击敌舰。',
    story:'搭载回天鱼雷的潜艇在太平洋战场执行了多次特攻任务,但由于美军反潜力量强大,效果有限。' },
  japan_shinyo: { name:'震洋特攻艇', cost:2, atk:4, hp:1, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    keywords:['rush'],
    desc:'装满炸药的摩托艇,撞击敌军舰船。',
    story:'“震洋”是日军在战争末期开发的自杀式摩托艇,计划在本土决战时使用,但未能大规模投入使用。' },
  japan_fukuryu: { name:'伏龙特攻队', cost:2, atk:4, hp:1, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    keywords:['stealth'],
    desc:'携带水雷潜水攻击敌舰的蛙人部队。',
    story:'“伏龙”是日军的水下特攻部队,潜水员携带水雷潜行至敌舰下方引爆,但由于设备和训练不足,实战效果有限。' },
  japan_ki61: { name:'三式战斗机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'“飞燕”,日本陆军的主力战斗机之一。',
    story:'三式战斗机“飞燕”由川崎公司研制,采用液冷发动机,是日本陆军在二战中性能最优秀的战斗机之一。' },
  japan_ki84: { name:'四式战斗机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['mobile'],
    desc:'“疾风”,与P-51和P-47抗衡的战斗机。',
    story:'四式战斗机“疾风”由中岛公司研制,是日本陆军在二战中最优秀的战斗机之一,被认为是能够与美军主力战斗机抗衡的机型。' },
  japan_ki43: { name:'一式战斗机', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    keywords:['mobile'],
    desc:'“隼”,轻巧灵活的陆军战斗机。',
    story:'一式战斗机“隼”由中岛公司研制,机动性优异,是日本陆军在战争初期的主力战斗机之一。' },
  japan_ki44: { name:'二式战斗机', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'“钟馗”,专为截击轰炸机设计。',
    story:'二式战斗机“钟馗”由中岛公司研制,装备重型武器,专门用于截击美军轰炸机。' },
  japan_ki45: { name:'二式复座战斗机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'“屠龙”,双发重型战斗机。',
    story:'二式复座战斗机“屠龙”由川崎公司研制,装备重型武器,可执行截击和对地攻击任务。' },
  japan_ki100: { name:'五式战斗机', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'使用液冷发动机的陆军战斗机。',
    story:'五式战斗机是日军在战争末期研制的战斗机,综合了四式战斗机的机动性和三式战斗机的火力,但产量有限。' },
  japan_a6m_zero: { name:'零战52型', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    keywords:['mobile'],
    desc:'零式战斗机的改进型,加强了火力和防护。',
    story:'零战52型是零式战斗机的重要改进型,通过加强结构和火力弥补了早期型号的缺点,但性能仍不及美军新锐战斗机。' },
  japan_a7m: { name:'烈风战斗机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['double'],
    desc:'零式的后继型号,性能优异但产量极少。',
    story:'“烈风”是日本海军在战争末期研制的新型战斗机,性能远超零式,但由于资源短缺和轰炸破坏,始终未能大量投产。' },
  japan_n1k: { name:'紫电改', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['double'],
    desc:'日本海军最优秀的战斗机之一。',
    story:'“紫电改”由川西公司研制,采用自动空战襟翼,低空机动性极为出色,被认为是日本在二战中最优秀的战斗机之一。' },
  japan_j2m: { name:'雷电战斗机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'专为截击轰炸机设计的高空战斗机。',
    story:'“雷电”由三菱公司研制,专门用于截击美军高空轰炸机,装备重型武器,但低空机动性较差。' },
  japan_d4y: { name:'彗星俯冲轰炸机', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    keywords:['rush'],
    desc:'舰载俯冲轰炸机,速度极快。',
    story:'“彗星”是日本海军的舰载俯冲轰炸机,速度较快,但在战争后期面对美军战斗机时生存率很低。' },
  japan_b6n: { name:'天山舰载攻击机', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'舰载鱼雷轰炸机,中途岛后投入使用。',
    story:'“天山”是日本海军在战争中期投入使用的舰载攻击机,综合性能优于九七舰攻,但飞行员素质已大不如前。' },
  japan_b7a: { name:'流星舰载攻击机', cost:5, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['rush'],
    desc:'新型舰载攻击机,速度快、载弹量大。',
    story:'“流星”是日本海军在战争末期研制的新型舰载攻击机,性能优异,但由于航母损失严重,主要作为陆基轰炸机使用。' },
  japan_g4m: { name:'一式陆攻', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'日本海军的中型轰炸机,曾击沉威尔士亲王号。',
    story:'一式陆上攻击机是日本海军的中型轰炸机,1941年在马来亚海域击沉了英国威尔士亲王号战列舰和反击号战列巡洋舰。' },
  japan_g3m: { name:'九六式陆攻', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'日本海军早期的中型轰炸机。',
    story:'九六式陆上攻击机是日本海军在战争初期的中型轰炸机,曾参与轰炸中国城市和击沉威尔士亲王号。' },
  japan_p1y: { name:'东海陆上巡逻机', cost:4, atk:3, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'装备雷达的反潜巡逻机。',
    story:'“东海”是日本海军研制的反潜巡逻机,装备雷达和磁探仪,但由于产量有限,未能有效应对美军潜艇的威胁。' },
  japan_h6k: { name:'九七式飞行艇', cost:4, atk:3, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'远程水上飞机,执行巡逻和侦察任务。',
    story:'九七式飞行艇是日本海军早期的远程水上飞机,在太平洋战争初期执行了多次远程侦察任务。' },
  japan_h8k: { name:'二式飞行艇', cost:5, atk:4, hp:5, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    desc:'当时世界上最先进的水上飞机之一。',
    story:'二式飞行艇(川西H8K)是二战中最优秀的水上飞机之一,航程超过7000公里,曾执行轰炸珍珠港的远程任务。' },
  japan_ki67: { name:'四式重爆', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'陆军重型轰炸机,速度快、火力强。',
    story:'四式重爆“飞龙”是日本陆军在战争后期研制的新型轰炸机,速度快、载弹量大,但产量有限。' },
  japan_ki21: { name:'九七式重爆', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'陆军早期重型轰炸机。',
    story:'九七式重型轰炸机是日本陆军在战争初期的主力轰炸机,参加了轰炸中国城市的作战。' },
  japan_ki49: { name:'九九式双轻爆', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'陆军双发轻型轰炸机。',
    story:'九九式双发轻型轰炸机是日本陆军在战争初期的主力轰炸机,机动性较好,但防护薄弱。' },
  japan_ki48: { name:'九七式轻爆', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'陆军单发轻型轰炸机,机动性好。',
    story:'九七式轻型轰炸机机动性出色,曾被日军飞行员用于执行各种高难度任务。' },
  japan_midget_sub: { name:'甲标的袖珍潜艇', cost:2, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    keywords:['stealth'],
    desc:'两人操作的袖珍潜艇,用于港口偷袭。',
    story:'甲标的袖珍潜艇是日本海军在珍珠港、悉尼港和马达加斯加等地使用的特种作战潜艇,战果有限。' },
  japan_cruiser_tone: { name:'利根号巡洋舰', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'装备水上飞机的重巡洋舰。',
    story:'利根号是日本海军最优秀的重巡洋舰之一,其独特之处在于所有主炮都布置在舰艏,舰艉用于搭载水上侦察机。' },
  japan_battleship_nagato: { name:'长门号战列舰', cost:6, atk:6, hp:7, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['guard'],
    desc:'日本海军的象征,联合舰队旗舰。',
    story:'长门号是日本海军最著名的战列舰之一,长期担任联合舰队旗舰,装备410毫米主炮,曾参与珍珠港作战。' },
  japan_akagi: { name:'赤城号航空母舰', cost:6, atk:5, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    desc:'偷袭珍珠港的旗舰航母。',
    story:'赤城号是日本海军的主力航母,担任偷袭珍珠港的旗舰,1942年在中途岛海战中被美军俯冲轰炸机击沉。' },
  japan_kaga: { name:'加贺号航空母舰', cost:6, atk:5, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    desc:'参与偷袭珍珠港的主力航母。',
    story:'加贺号是日本海军的主力航母,参与了偷袭珍珠港,1942年在中途岛海战中被美军击沉。' },
  japan_hiryu: { name:'飞龙号航空母舰', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'中途岛海战中的日军航母。',
    story:'飞龙号是日本海军的中型航母,中途岛海战中在友舰被击沉后发起反击,重创美军约克城号,最终被击沉。' },
  japan_shokaku: { name:'翔鹤号航空母舰', cost:6, atk:5, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    desc:'日本海军最优秀的舰队航母之一。',
    story:'翔鹤号是日本海军在战争中最活跃的舰队航母之一,参与了多次重大海战,1944年在菲律宾海战中被美军潜艇击沉。' },
  japan_zuikaku: { name:'瑞鹤号航空母舰', cost:6, atk:5, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    desc:'与翔鹤号并称的精英航母。',
    story:'瑞鹤号是日本海军在战争中最活跃的航母之一,参加了从珍珠港到莱特湾的一系列重要海战,1944年在恩加尼奥角海战中被击沉。' },
  japan_taiho: { name:'大凤号航空母舰', cost:6, atk:5, hp:7, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['guard'],
    desc:'日本海军最现代化的装甲航母。',
    story:'大凤号是日本海军第一艘采用装甲飞行甲板的航母,1944年在菲律宾海海战中被美军潜艇击沉,损失惨重。' },
  japan_kongo: { name:'金刚号战列舰', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    keywords:['mobile'],
    desc:'高速战列舰,曾参与瓜岛炮击。',
    story:'金刚号是日本海军的高速战列舰,在瓜达尔卡纳尔战役中参与了对亨德森机场的炮击,1944年被美军潜艇击沉。' },
  japan_ise: { name:'伊势号战列舰', cost:6, atk:5, hp:6, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'改造为航空战列舰的老式战舰。',
    story:'伊势号原本是战列舰,后改造为“航空战列舰”,在舰艉搭载水上飞机,但改造效果不佳。' },
  japan_yamashiro: { name:'山城号战列舰', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'老式战列舰,在苏里高海峡被击沉。',
    story:'山城号是日本海军的老式战列舰,1944年在苏里高海峡夜战中被美军战列舰编队击沉。' },
  japan_mogami: { name:'最上号巡洋舰', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'装备水上飞机的重巡洋舰。',
    story:'最上号是日本海军的一艘重巡洋舰,在苏里高海峡夜战中被美军重创后自沉。' },
  japan_jintsu: { name:'神通号轻巡洋舰', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    desc:'轻巡洋舰,担任水雷战队的旗舰。',
    story:'神通号是日本海军的轻巡洋舰,在科隆班加拉海战中被美军雷达火控的战舰击沉。' },
  japan_yukikaze: { name:'雪风号驱逐舰', cost:3, atk:3, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    desc:'传奇的幸运舰,多次出击而几乎无损。',
    story:'雪风号是日本海军最著名的驱逐舰之一,参加了多次重大战役却几乎毫无损失,战后被作为赔偿舰移交给中国。' },
  japan_kagero: { name:'阳炎型驱逐舰', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'japan',
    keywords:['mobile'],
    desc:'日本海军最优秀的驱逐舰之一。',
    story:'阳炎型驱逐舰是日本海军在二战中最优秀的驱逐舰之一,装备强大的鱼雷武器,用于水雷战队的夜间突袭。' },
  japan_shimakaze: { name:'岛风号驱逐舰', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    keywords:['mobile'],
    desc:'高速驱逐舰,装备15具鱼雷发射管。',
    story:'岛风号是日本海军最快的驱逐舰,装备15具鱼雷发射管,1944年在奥尔莫克湾海战中被美军舰载机击沉。' },
  japan_i400: { name:'伊-400潜艇', cost:6, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['stealth'],
    desc:'能搭载水上攻击机的巨型潜艇。',
    story:'伊-400是当时世界上最大的潜艇,可搭载3架水上攻击机,计划用于袭击巴拿马运河,但未能完成任务。' },
  japan_ha101: { name:'一式中型坦克', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'战争中后期日军最优秀的中型坦克。',
    story:'一式中型坦克是日本在战争后期研制的中型坦克,装备47毫米长身管火炮,但主要用于本土防御。' },
  japan_chi_he: { name:'三式中型坦克', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'装备75毫米坦克炮,用于对抗美军坦克。',
    story:'三式中型坦克装备75毫米坦克炮,是日军为对抗谢尔曼坦克而研制的,但产量有限且未大量参战。' },
  japan_chi_ri: { name:'四式中型坦克', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'japan',
    desc:'日军在战争末期研制的新型坦克。',
    story:'四式中型坦克装备75毫米长身管火炮,性能接近美军谢尔曼坦克,但仅生产了两辆样车,从未参战。' },
  japan_chi_to: { name:'五式中型坦克', cost:6, atk:6, hp:6, type:'unit', unitType:'land', rarity:'epic', nation:'japan',
    desc:'日军在战争末期研制的最先进坦克。',
    story:'五式中型坦克是日本在战争末期研制的最先进坦克,装备75毫米火炮,但仅完成一辆原型车,从未投入实战。' },
  japan_kai_chi: { name:'九七改中型坦克', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'九七式的改进型,装备47毫米火炮。',
    story:'九七改中型坦克是九七式的改进型号,装备47毫米长身管火炮,火力较原型有较大提升。' },
  japan_ka_mi: { name:'卡米轻型坦克', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'用于本土决战计划的轻型坦克。',
    story:'卡米轻型坦克是日军为本土决战而研制的轻型坦克,装备37毫米火炮,用于迟滞美军推进。' },
  japan_so_ki: { name:'装甲车', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    keywords:['mobile'],
    desc:'用于侦察和步兵支援的装甲车辆。',
    story:'日军装备了多种轮式装甲车,用于战场侦察和步兵支援,在太平洋岛屿作战中也有使用。' },
  japan_ho_ni: { name:'一式炮战车', cost:4, atk:5, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'装备75毫米火炮的自行火炮。',
    story:'一式炮战车“霍尼”是日军以九七式中型坦克为底盘改装的自行火炮,装备75毫米火炮,用于反坦克和火力支援。' },
  japan_ho_ro: { name:'九四式装甲车', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'装甲输送车,用于运输步兵。',
    story:'九四式装甲车是日军使用的一种履带式装甲输送车,主要用于运输步兵和物资。' },
  japan_ka_chi: { name:'九五式轻战车', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    keywords:['mobile'],
    desc:'日军轻型坦克,广泛用于中国战场。',
    story:'九五式轻型坦克是日军在中国和东南亚战场使用的主要轻型坦克,装备37毫米火炮。' },
  japan_te_ke: { name:'九四式轻装甲车', cost:1, atk:1, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    keywords:['mobile'],
    desc:'小型装甲车,用于侦察和联络。',
    story:'九四式轻装甲车是日军的一种小型履带式装甲车,主要用于侦察和联络任务。' },
  japan_ha_go_diesel: { name:'九五式柴油型', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'japan',
    desc:'换装柴油发动机的九五式坦克。',
    story:'九五式轻型坦克的柴油型装备柴油发动机,提高了可靠性和燃油经济性,是日军轻型坦克的重要改进型。' },
  japan_ss_ki: { name:'试制四式轻战车', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'japan',
    desc:'战争末期研制的新型轻型坦克。',
    story:'试制四式轻战车是日军在战争末期研制的新型轻型坦克,装备57毫米火炮,用于本土决战。' },
  japan_imperial_rescript: { name:'军人敕谕', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +2/+1。',
    story:'《军人敕谕》是明治天皇颁布的军人训令,强调忠节、礼仪、武勇、信义和质素,是日军思想教育的重要文件。' },
  japan_gyokusai: { name:'玉碎', cost:3, atk:0, hp:0, type:'command', rarity:'epic', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:0, hp:4 },
    desc:'作战令:点击我方总部,全体单位 +0/+4。',
    story:'“玉碎”意为宁为玉碎不为瓦全,是日军在太平洋岛屿防御战中的战术指导思想,要求守军战至最后一人。' },
  japan_tenno_heika: { name:'天皇陛下万岁', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:3, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +3/+0。',
    story:'日军士兵在冲锋和自杀式攻击时高呼“天皇陛下万岁”,这一口号成为日军在绝境中作战的精神支柱。' },
  japan_kokutai: { name:'国体护持', cost:2, atk:0, hp:0, type:'command', rarity:'common', nation:'japan',
    target:'player_hq', effect:{ type:'heal_hq', value:5 },
    desc:'作战令:点击我方总部,恢复 5 点生命。',
    story:'“国体护持”是日本战争末期的政治口号,强调维护天皇制国家体制,成为负隅顽抗的思想基础。' },
  japan_totsugeki: { name:'突击命令', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +2/+0。',
    story:'日军在作战中强调主动进攻和近战,突击命令常常要求部队不惜代价发起攻击。' },
  japan_bushido_code: { name:'武士道', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'heal_hq', value:4 },
    desc:'作战令:点击我方总部,恢复 4 点生命。',
    story:'武士道强调忠诚、荣誉和牺牲精神,是日军思想教育的重要内容,也是日军在战场上宁死不降的原因之一。' },
  japan_naval_drill: { name:'海军训练', cost:3, atk:0, hp:0, type:'command', rarity:'common', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +1/+2。',
    story:'日本海军以其严格的训练和精湛的夜战技术著称,在战争初期培养了大量优秀的飞行员和水兵。' },
  japan_banzai_charge: { name:'万岁突击', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:5 },
    desc:'作战令:点击敌方单位或敌方总部,造成 5 点伤害。',
    story:'万岁突击是日军在战局不利时发动的自杀式攻击,虽然常常全军覆没,但也给盟军造成了一定的心理压力。' },
  japan_suicide_attack: { name:'特攻作战', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'japan',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:7 },
    desc:'作战令:点击敌方单位或敌方总部,造成 7 点伤害。',
    story:'战争末期,日军发动了一系列特攻作战,包括神风特攻、回天鱼雷、樱花特攻机等,企图以生命为代价挽回败局。' },
  japan_island_ambush: { name:'岛屿伏击', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'japan',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:3 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 3 点伤害。',
    story:'日军在太平洋岛屿防御中常利用丛林和地下工事伏击登陆的美军,给美军造成重大伤亡。' },
  japan_bunker_defense: { name:'要塞防御', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'japan',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:4 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 4 点。',
    story:'日军在太平洋岛屿上构筑了复杂的地下工事网络,依托坚固阵地顽强抵抗,给美军造成巨大伤亡。' },
  japan_night_battle: { name:'夜战', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'japan',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 4 点伤害。',
    story:'日本海军擅长夜战,在战争初期凭借精湛的夜战技术和训练有素的官兵,多次在夜战中占据优势。' },
  japan_banzai_counter: { name:'肉弹攻击', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'japan',
    trigger:'enemy_deploy', effect:{ type:'damage_hq', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对敌方总部造成 4 点伤害。',
    story:'日军在太平洋岛屿防御中大量使用肉弹攻击战术,士兵携带炸药包冲向美军坦克和阵地。' },
  japan_air_defense_counter: { name:'本土防空', cost:2, atk:0, hp:0, type:'counter', rarity:'common', nation:'japan',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:3 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 3 点。',
    story:'战争后期美军对日本本土展开大规模轰炸,日军以高射炮和战斗机拦截,但未能阻止轰炸的进行。' },
  japan_kaiten_counter: { name:'回天特攻', cost:4, atk:0, hp:0, type:'counter', rarity:'rare', nation:'japan',
    trigger:'enemy_deploy', effect:{ type:'damage_hq', value:5 },
    desc:'应变:布下后,敌方部署单位时触发,对敌方总部造成 5 点伤害。',
    story:'回天鱼雷由人操纵向目标,操作员在接近敌舰时手动控制方向,最终撞击目标,是一种极端的特攻武器。' },
  japan_gyokusai_counter: { name:'全员玉碎', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'japan',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:5 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 5 点伤害。',
    story:'“全员玉碎”是日军在岛屿防御战中的作战要求,要求守军战至最后一人,绝不投降。' },
  japan_torpedo_squadron: { name:'水雷战队', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    keywords:['rush'],
    desc:'擅长夜间鱼雷攻击的驱逐舰编队。',
    story:'日本海军的水雷战队以夜间鱼雷攻击闻名,在战争初期多次重创盟军舰队,但随着美军雷达技术的普及,其优势逐渐丧失。' },
  japan_air_wing: { name:'航空战队', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'由航母舰载机组成的精锐航空部队。',
    story:'日本海军的航空战队在战争初期拥有世界上最优秀的飞行员,在珍珠港、印度洋和珊瑚海等战役中取得了辉煌的战果。' },
  japan_special_attack_unit: { name:'特攻队', cost:4, atk:5, hp:1, type:'unit', unitType:'ranged', rarity:'epic', nation:'japan',
    keywords:['rush'],
    desc:'以生命为代价的自杀式攻击部队。',
    story:'特攻队在战争末期大量组建,包括神风特攻队、回天特攻队和伏龙特攻队等,以生命为代价攻击盟军目标。' },
  japan_naval_aviation: { name:'海军航空队', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'japan',
    desc:'日本海军的精锐陆基航空部队。',
    story:'海军航空队在战争初期拥有大量优秀飞行员,在太平洋战场的空战中取得了辉煌战果。' },
  japan_imperial_way: { name:'皇道精神', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'japan',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +2/+2。',
    story:'皇道精神是日本军国主义的核心思想,强调天皇的神圣地位和日本民族的优越性,成为日军的精神支柱。' },
          /* ==================== 英国 · 老卡 ==================== */
  uk_churchill: { name:'丘吉尔坦克', cost:4, atk:4, hp:6, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'装甲厚重的步兵坦克,以英国首相命名。',
    story:'丘吉尔坦克是英国在二战中最重要的步兵坦克之一,装甲厚重,能承受德军反坦克炮的多次命中,主要用于伴随步兵突破。' },
  uk_matilda: { name:'玛蒂尔达II', cost:3, atk:3, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['guard'],
    desc:'北非战场上被称为“沙漠女王”的步兵坦克。',
    story:'玛蒂尔达II在1940至1941年的北非战场上表现出色,装甲足以抵御意军和德军大部分反坦克炮,被英军士兵称为“沙漠女王”。' },
  uk_hurricane: { name:'飓风战斗机', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'不列颠空战中的主力战斗机。',
    story:'飓风战斗机在不列颠空战中击落的敌机数量超过其他所有英军战斗机之和,是皇家空军在不列颠空战中的中坚力量。' },
  uk_spitfire: { name:'喷火战斗机', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    keywords:['double'],
    desc:'外形优雅、性能优异的传奇战斗机。',
    story:'喷火战斗机是英国在二战中最著名的战斗机,其椭圆形机翼设计优美,性能优异,在不列颠空战中与飓风并肩作战。' },
  uk_lancaster: { name:'兰开斯特轰炸机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    desc:'皇家空军夜间轰炸的主力重型轰炸机。',
    story:'兰开斯特是英国皇家空军最重要的夜间重型轰炸机,载弹量大,执行了对德国城市的战略轰炸任务。' },
  uk_raf: { name:'皇家空军', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'世界上历史最悠久的独立空军。',
    story:'英国皇家空军成立于1918年,是世界上第一支独立于陆海军的空军力量。不列颠空战的胜利使其名垂青史。' },
  uk_home_guard: { name:'国民自卫军', cost:1, atk:1, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'由平民组成的本土防御力量。',
    story:'国民自卫军是英国在二战中组建的民兵组织,成员多为退伍军人和志愿者,负责本土防御和巡逻任务。' },
  uk_convoy: { name:'大西洋护航队', cost:2, atk:1, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'维系英国生命的商船队。',
    story:'大西洋护航队是英国在二战中的生命线,商船队在大西洋上运送物资,由皇家海军和加拿大海军护航。' },
  uk_commandos: { name:'皇家突击队', cost:3, atk:4, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['rush'],
    desc:'深入敌后执行突袭的精锐部队。',
    story:'皇家突击队在二战中执行了多次突袭任务,包括圣纳泽尔船坞袭击和迪耶普登陆,给德军造成了不小的困扰。' },
  uk_desert_rats: { name:'沙漠之鼠', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['mobile'],
    desc:'第7装甲师的绰号,北非战场上的劲旅。',
    story:'第7装甲师在北非战场上以鼠形臂章闻名,与隆美尔的非洲军团周旋,屡立战功。' },
  uk_intelligence: { name:'情报部门', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:3 },
    desc:'作战令:点击敌方单位或敌方总部,造成 3 点伤害。',
    story:'英国情报部门在二战中成功破译了德军恩尼格玛密码,为盟军提供了大量关键情报。' },
  uk_radar: { name:'雷达站', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'heal_hq', value:5 },
    desc:'作战令:点击我方总部,恢复 5 点生命。',
    story:'英国在二战前建立的雷达站网络“本土链”,为皇家空军提供了关键的预警信息,是不列颠空战胜利的重要因素。' },
  uk_arsenal: { name:'兵工厂', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +1/+1。',
    story:'英国在二战期间动员全国工业力量生产武器装备,兵工厂日夜不停地为前线提供武器弹药。' },
  uk_montgomery: { name:'蒙哥马利将军', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +2/+2。',
    story:'蒙哥马利将军指挥英军在北非阿拉曼战役中击败隆美尔,后指挥诺曼底登陆的地面部队。' },
  uk_dunkirk: { name:'敦刻尔克撤退', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'heal_hq', value:6 },
    desc:'作战令:点击我方总部,恢复 6 点生命。',
    story:'1940年5月,英法联军从敦刻尔克撤退,英国动用一切可用船只将33万士兵撤回本土。' },
  uk_battle_britain: { name:'不列颠空战', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'uk',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:6 },
    desc:'作战令:点击敌方单位或敌方总部,造成 6 点伤害。',
    story:'不列颠空战是二战中规模最大的空战,皇家空军成功抵御了德国空军的进攻,粉碎了德军入侵英国的计划。' },
  uk_el_alamein: { name:'阿拉曼战役', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +2/+0。',
    story:'1942年阿拉曼战役的胜利扭转了北非战局,丘吉尔评价:“在阿拉曼之前,我们从未取得过胜利。”' },
  uk_bomber_command: { name:'轰炸机司令部', cost:5, atk:0, hp:0, type:'command', rarity:'epic', nation:'uk',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:7 },
    desc:'作战令:点击敌方单位或敌方总部,造成 7 点伤害。',
    story:'英国皇家空军轰炸机司令部对德国本土进行了持续的战略轰炸,严重削弱了德国的战争工业。' },
  uk_8th_army: { name:'第8集团军', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'北非战场上的英军主力。',
    story:'英国第8集团军在北非战场上与隆美尔的非洲军团多次交战,最终在阿拉曼战役中取得决定性胜利。' },
  uk_14th_army: { name:'第14集团军', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'缅甸战场上的英军主力。',
    story:'英国第14集团军在斯利姆将军指挥下,在缅甸战场击败日军,收复了缅甸。' },
  uk_soe: { name:'特别行动执行处', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'uk',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 4 点伤害。',
    story:'特别行动执行处(SOE)是英国在二战中专门从事破坏和颠覆活动的秘密机构,向欧洲被占领国家派遣了大量特工。' },
  uk_bren_gun: { name:'布伦机枪', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'英军步兵班的火力支柱。',
    story:'布伦轻机枪是英军在二战中最重要的班组支援武器,可靠性高,广泛装备于步兵部队。' },
  uk_sten_gun: { name:'司登冲锋枪', cost:1, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'结构简单、造价低廉的冲锋枪。',
    story:'司登冲锋枪是英国在二战中大量生产的冲锋枪,结构简单、造价低廉,大量装备给突击队和抵抗组织。' },
  uk_piat: { name:'PIAT反坦克发射器', cost:2, atk:3, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['firststrike'],
    desc:'英军步兵的反坦克武器。',
    story:'PIAT是英国在二战中使用的步兵反坦克武器,采用弹簧发射,没有后坐力,适合在狭窄空间使用。' },
  uk_aa_gun: { name:'防空炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'守卫英国城市和港口的防空火力。',
    story:'英国在二战中部署了大量防空炮,配合雷达和拦阻气球,有效抵御了德军的空袭。' },
  uk_naval_gun: { name:'舰炮支援', cost:3, atk:0, hp:0, type:'command', rarity:'common', nation:'uk',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:4 },
    desc:'作战令:点击敌方单位或敌方总部,造成 4 点伤害。',
    story:'英国皇家海军的舰炮在诺曼底登陆和地中海战场为地面部队提供了关键的火力支援。' },
  uk_glider_pilot: { name:'滑翔机飞行员', cost:3, atk:3, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['rush'],
    desc:'驾驶滑翔机在敌后降落的精锐部队。',
    story:'英国空降部队的滑翔机飞行员在诺曼底登陆夜驾驶滑翔机降落在奥恩河畔,成功夺取佩加索斯桥。' },
  uk_radar_warning: { name:'雷达预警', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'uk',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:4 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 4 点。',
    story:'英国在二战中建立的雷达预警网络为皇家空军提供了关键的预警信息,是不列颠空战胜利的重要因素。' },
      /* ==================== 英国 · 新增卡牌(100 张) ==================== */
  uk_1st_infantry: { name:'第1步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'英国远征军的老牌部队,从法国战场一路打到北非。',
    story:'第1步兵师是英国陆军历史最悠久的师之一,1940年从敦刻尔克撤回后,参加了北非和意大利战役。' },
  uk_2nd_infantry: { name:'第2步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'英国远征军主力,在法国战役中损失惨重。',
    story:'第2步兵师在1940年法国战役中担任英国远征军的后卫,在敦刻尔克撤退中掩护主力撤离,损失惨重。' },
  uk_3rd_infantry: { name:'第3步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['guard'],
    desc:'绰号“铁师”,蒙哥马利曾经指挥过的老牌部队。',
    story:'第3步兵师绰号“铁师”,蒙哥马利在二战前曾指挥该师。该师参加了诺曼底登陆并一路推进到德国本土。' },
  uk_4th_infantry: { name:'第4步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'在北非和意大利战场作战的老牌步兵师。',
    story:'第4步兵师在二战中参加了北非、意大利和希腊等战役,作战经验丰富。' },
  uk_5th_infantry: { name:'第5步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'在意大利山地战中与德军反复拉锯。',
    story:'第5步兵师在意大利战场参加了卡西诺山战役等一系列艰苦战斗。' },
  uk_6th_airborne: { name:'第6空降师', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['rush'],
    desc:'诺曼底登陆夜的先锋,夺取佩加索斯桥。',
    story:'第6空降师在诺曼底登陆夜乘坐滑翔机降落在奥恩河畔,成功夺取佩加索斯桥,阻止德军装甲部队增援海滩。' },
  uk_1st_airborne: { name:'第1空降师', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['guard'],
    desc:'在阿纳姆大桥上死战不退的“红魔”。',
    story:'第1空降师在1944年“市场花园”行动中被空投至阿纳姆,与德军装甲部队激战九天,几乎全军覆没。' },
  uk_51st_highland: { name:'第51高地师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'来自苏格兰高地,以顽强著称。',
    story:'第51高地师绰号“公路师”,在1940年法国战役中被围困于圣瓦莱里,后重建并参加了北非和西北欧战役。' },
  uk_15th_scottish: { name:'第15苏格兰师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'在北非和意大利战场作战的苏格兰部队。',
    story:'第15苏格兰师参加了西西里登陆和意大利本土作战,在卡西诺山战役中付出重大伤亡。' },
  uk_50th_northumbrian: { name:'第50诺森伯兰师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'绰号“泰恩赛德师”,在诺曼底登陆中与美军并肩作战。',
    story:'第50诺森伯兰师绰号“泰恩赛德师”,在诺曼底登陆中与美军第1步兵师协同作战,付出了重大代价。' },
  uk_43rd_wessex: { name:'第43威塞克斯师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'“威塞克斯师”,在诺曼底灌木丛战中锤炼出的部队。',
    story:'第43威塞克斯师在诺曼底战役中经历了艰苦的灌木丛战斗,随后参加了“市场花园”行动。' },
  uk_53rd_welsh: { name:'第53威尔士师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'“威尔士师”,在诺曼底和荷兰战场作战。',
    story:'第53威尔士师在诺曼底战役中攻占了“112高地”,随后参加了市场花园行动和莱茵河渡河作战。' },
  uk_49th_west_riding: { name:'第49西赖丁师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'“北极熊师”,在诺曼底和比利时作战。',
    story:'第49西赖丁师绰号“北极熊师”,在诺曼底登陆后攻占了勒阿弗尔港。' },
  uk_56th_london: { name:'第56伦敦师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'来自伦敦的国民警卫队部队。',
    story:'第56伦敦师由伦敦的国民警卫队组成,参加了意大利和西北欧战役。' },
  uk_78th_infantry: { name:'第78步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'“战斧师”,在北非突尼斯战役中与德军血战。',
    story:'第78步兵师绰号“战斧师”,在突尼斯战役中首次参战,随后参加了意大利和西北欧的一系列作战。' },
  uk_46th_infantry: { name:'第46步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'在意大利战场作战的老牌步兵师。',
    story:'第46步兵师绰号“橡树师”,在意大利战场参加了卡西诺山战役和哥特防线作战。' },
  uk_44th_infantry: { name:'第44步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'“家郡师”,在诺曼底和荷兰战场作战。',
    story:'第44步兵师绰号“家郡师”,在诺曼底战役中攻占卡昂,后参加市场花园行动。' },
  uk_gurkhas: { name:'廓尔喀部队', cost:3, atk:4, hp:3, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['rush'],
    desc:'来自尼泊尔的勇猛战士,手持弯刀冲锋陷阵。',
    story:'廓尔喀部队是英军中最勇猛的部队之一,他们手持廓尔喀弯刀,在意大利和缅甸战场表现出色。' },
  uk_black_watch: { name:'黑卫士', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'苏格兰高地精锐团,以风笛和勇猛著称。',
    story:'黑卫士是英国陆军最著名的苏格兰高地团之一,参加了从法国到德国的整个欧洲战场的作战。' },
  uk_coldstream: { name:'冷溪卫队', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'英国陆军最古老的团之一,白金汉宫卫兵。',
    story:'冷溪卫队是英国近卫步兵中历史最悠久的团,二战中参加了诺曼底和西北欧战役。' },
  uk_grenadier: { name:'掷弹兵卫队', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'英国近卫步兵中的精锐团。',
    story:'掷弹兵卫队是英国近卫步兵中级别最高的团,二战中在北非和欧洲战场作战。' },
  uk_scots_guards: { name:'苏格兰卫队', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'近卫步兵中的苏格兰部队。',
    story:'苏格兰卫队是英国近卫步兵的五个团之一,参加了诺曼底登陆和西北欧战役。' },
  uk_irish_guards: { name:'爱尔兰卫队', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    desc:'近卫步兵中的爱尔兰部队。',
    story:'爱尔兰卫队在二战中参加了北非和意大利战役,以顽强的战斗作风著称。' },
  uk_welsh_guards: { name:'威尔士卫队', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    desc:'近卫步兵中的威尔士部队。',
    story:'威尔士卫队是英国近卫步兵的五个团之一,二战中参加了意大利和西北欧战场作战。' },
  uk_paras: { name:'降落伞团', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['rush'],
    desc:'“红魔”,英国空降部队的传奇番号。',
    story:'英国降落伞团绰号“红魔”,士兵佩戴红色贝雷帽,在诺曼底、阿纳姆和莱茵河渡河作战中屡立战功。' },
  uk_chindits: { name:'钦迪特远程突击队', cost:4, atk:4, hp:3, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['stealth'],
    desc:'深入缅甸丛林的远程突击部队。',
    story:'钦迪特是英国在缅甸战场组建的远程突击部队,深入日军后方执行破坏铁路和袭击补给线的任务。' },
  uk_sas_jeep: { name:'SAS吉普队', cost:3, atk:3, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['mobile'],
    desc:'驾驶吉普车穿越沙漠,袭击德军机场。',
    story:'SAS吉普队装备多挺机枪的吉普车,在北非沙漠中深入敌后,摧毁了数百架停放在机场的德军飞机。' },
  uk_lrdg: { name:'远程沙漠作战群', cost:4, atk:4, hp:3, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['stealth'],
    desc:'深入撒哈拉沙漠执行侦察和突袭任务的精英。',
    story:'远程沙漠作战群(LRDG)在北非沙漠中执行远程侦察和突袭任务,为SAS和其他部队提供情报支持。' },
  uk_rifle_brigade: { name:'步枪旅', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['mobile'],
    desc:'英国陆军历史最悠久的团,擅长机械化和侦察作战。',
    story:'步枪旅是英国陆军最著名的团之一,二战中作为机械化步兵和侦察部队作战,被称为“绿夹克”。' },
  uk_guards_armoured: { name:'近卫装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['guard'],
    desc:'英国最精锐的装甲师,装备克伦威尔坦克。',
    story:'近卫装甲师是英国陆军最精锐的装甲部队之一,在诺曼底登陆后参加了西北欧的一系列重大作战。' },
  uk_11th_armoured: { name:'第11装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['rush'],
    desc:'“黑公牛师”,在诺曼底和莱茵河作战。',
    story:'第11装甲师绰号“黑公牛师”,在诺曼底登陆后参加了“埃普索姆”行动和莱茵河渡河作战。' },
  uk_1st_armoured: { name:'第1装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    desc:'在北非和意大利战场作战的老牌装甲师。',
    story:'第1装甲师在北非战场与隆美尔的非洲军团多次交战,后参加意大利战役,付出了重大伤亡。' },
  uk_7th_armoured_desert: { name:'第7装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['mobile'],
    desc:'“沙漠之鼠”的主力,在北非与隆美尔周旋。',
    story:'第7装甲师绰号“沙漠之鼠”,是北非战场上的英军主力,以鼠形臂章闻名。' },
  uk_79th_armoured: { name:'第79装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    desc:'“霍巴特滑稽坦克”的试验部队。',
    story:'第79装甲师由珀西·霍巴特少将指挥,专门装备各种特殊用途的“滑稽坦克”,如扫雷坦克、喷火坦克和架桥坦克。' },
  uk_cromwell: { name:'克伦威尔坦克', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['mobile'],
    desc:'英国巡洋坦克的代表,速度快、机动性好。',
    story:'克伦威尔坦克是英国在二战中后期的主力巡洋坦克,装备75毫米火炮,以速度快著称。' },
  uk_comet: { name:'彗星坦克', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['mobile'],
    desc:'英国在二战中最好的坦克之一。',
    story:'彗星坦克装备77毫米高速火炮,是英国在二战中综合性能最好的坦克,1945年初投入战场。' },
  uk_crusader: { name:'十字军坦克', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['mobile'],
    desc:'北非战场上的英军主力巡洋坦克。',
    story:'十字军坦克是英军在北非战场的主力坦克之一,速度快但装甲薄弱,在沙漠中被德军称为“沙地兔子”。' },
  uk_valentine: { name:'瓦伦丁坦克', cost:3, atk:3, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['guard'],
    desc:'可靠的步兵坦克,大量提供给苏联。',
    story:'瓦伦丁步兵坦克以可靠性著称,英国通过租借法案向苏联提供了大量瓦伦丁坦克,苏军对其评价很高。' },
  uk_cavalier: { name:'骑士坦克', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'巡洋坦克的早期型号,性能一般。',
    story:'骑士坦克是英国巡洋坦克的早期型号,由于发动机可靠性问题,主要用作训练和侦察。' },
  uk_challenger: { name:'挑战者坦克', cost:4, atk:5, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['firststrike'],
    desc:'装备17磅火炮的克伦威尔改进型。',
    story:'挑战者坦克以克伦威尔为底盘,装备17磅火炮,专门用于反坦克作战。' },
  uk_firefly: { name:'萤火虫坦克', cost:4, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'uk',
    keywords:['firststrike'],
    desc:'装备17磅火炮的谢尔曼,德军坦克的克星。',
    story:'萤火虫是以谢尔曼坦克为底盘,换装英国17磅火炮的改进型,是盟军唯一能在正常交战距离击穿虎式坦克正面装甲的坦克。' },
  uk_archer: { name:'弓箭手坦克歼击车', cost:4, atk:5, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['firststrike'],
    desc:'装备17磅火炮的自行反坦克炮。',
    story:'弓箭手坦克歼击车以瓦伦丁坦克为底盘,装备17磅火炮,其独特之处在于火炮朝后安装。' },
  uk_achilles: { name:'阿喀琉斯坦克歼击车', cost:4, atk:5, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['firststrike'],
    desc:'以M10为底盘改装17磅火炮的歼击车。',
    story:'阿喀琉斯是以美国M10坦克歼击车为底盘,换装英国17磅火炮的改进型,火力大幅提升。' },
  uk_daimler: { name:'戴姆勒装甲车', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['mobile'],
    desc:'英国陆军广泛使用的轮式装甲车。',
    story:'戴姆勒装甲车装备40毫米火炮,机动性好,广泛用于战场侦察和侧翼掩护。' },
  uk_humber: { name:'亨伯装甲车', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['mobile'],
    desc:'四轮装甲车,用于侦察和火力支援。',
    story:'亨伯装甲车是英国陆军在二战中使用的四轮装甲车,广泛装备于侦察部队。' },
  uk_universal_carrier: { name:'通用载具', cost:1, atk:1, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['mobile'],
    desc:'“布伦机枪车”,英国步兵的机动运输工具。',
    story:'通用载具是英国在二战中生产数量最多的装甲车辆,用于运输步兵、武器和弹药,也改装为多种支援车型。' },
  uk_matilda_cs: { name:'玛蒂尔达CS', cost:3, atk:2, hp:6, type:'unit', unitType:'land', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'装备榴弹炮的近距离支援型玛蒂尔达。',
    story:'玛蒂尔达CS(近距离支援型)装备76毫米榴弹炮,用于为步兵提供火力支援。' },
  uk_covenanter: { name:'契约者坦克', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'巡洋坦克,因发动机问题主要用作训练。',
    story:'契约者坦克是英国巡洋坦克的早期型号,由于发动机冷却系统问题,从未参加过实战,主要用于训练。' },
  uk_centaur: { name:'半人马坦克', cost:3, atk:3, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    desc:'克伦威尔的早期型号,用于训练和支援。',
    story:'半人马坦克是克伦威尔坦克的早期型号,装备不同发动机,主要用于训练和近距离支援。' },
  uk_tetrarch: { name:'领主坦克', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'uk',
    keywords:['mobile'],
    desc:'轻型坦克,曾提供给苏联。',
    story:'领主轻型坦克是英国在二战初期使用的轻型坦克,部分通过租借法案提供给苏联,用于侦察任务。' },
  uk_25pdr: { name:'25磅炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    desc:'英国陆军最优秀的野战火炮。',
    story:'25磅炮是英军在二战中最重要的野战火炮,既能执行反坦克任务,也能作为榴弹炮使用。' },
  uk_17pdr: { name:'17磅反坦克炮', cost:4, atk:5, hp:2, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['firststrike'],
    desc:'盟军最优秀的反坦克炮之一,能击穿虎式坦克。',
    story:'17磅反坦克炮是英国在二战中威力最大的反坦克炮,能在正常交战距离击穿虎式和豹式坦克的正面装甲。' },
  uk_6pdr: { name:'6磅反坦克炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'英军主力反坦克炮,从北非打到欧洲。',
    story:'6磅反坦克炮是英军在二战中后期的主力反坦克炮,能击穿大多数德军坦克的装甲。' },
  uk_4_5_inch: { name:'4.5英寸火炮', cost:4, atk:5, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    desc:'中型野战炮,射程远威力大。',
    story:'4.5英寸中型野战炮是英军重要的火炮之一,主要用于压制德军炮兵和摧毁工事。' },
  uk_5_5_inch: { name:'5.5英寸火炮', cost:5, atk:6, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    desc:'重型野战炮,能发射100磅炮弹。',
    story:'5.5英寸中型火炮是英国在二战中最重要的重型火炮,能发射100磅重的炮弹,威力巨大。' },
  uk_3_7_inch_aa: { name:'3.7英寸高射炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'英国最重要的重型防空炮。',
    story:'3.7英寸高射炮是英国在二战中最重要的重型防空火炮,也常被用于反坦克作战。' },
  uk_sexton: { name:'司事自行火炮', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    desc:'以谢尔曼为底盘,装备25磅炮的自行火炮。',
    story:'司事自行火炮以加拿大生产的谢尔曼坦克为底盘,装备25磅炮,是英军主要的自行火炮。' },
  uk_bishop: { name:'主教自行火炮', cost:3, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'以瓦伦丁为底盘,装备25磅炮的自行火炮。',
    story:'主教自行火炮以瓦伦丁坦克为底盘,装备25磅炮,主要用于北非战场的火力支援。' },
  uk_archer_spg: { name:'弓箭手自行火炮', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    keywords:['firststrike'],
    desc:'火炮朝后安装的自行反坦克炮。',
    story:'弓箭手自行火炮以瓦伦丁坦克为底盘,装备17磅火炮,其火炮朝后安装,便于快速撤退。' },
  uk_bofors: { name:'博福斯高射炮', cost:2, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'中口径防空炮,盟军广泛使用。',
    story:'40毫米博福斯高射炮是英军在二战中最重要的中口径防空武器,能有效对付低空飞行的敌机。' },
  uk_typhoon: { name:'台风战斗机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['rush'],
    desc:'装备火箭弹的战斗轰炸机,专打德军装甲部队。',
    story:'台风战斗机装备四门机炮和火箭弹,是盟军最有效的对地攻击机之一,在诺曼底战役中摧毁了大量德军坦克。' },
  uk_tempest: { name:'暴风战斗机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['rush'],
    desc:'英国最快的低空战斗机,拦截V-1飞弹。',
    story:'暴风战斗机是英国在二战中最快的低空战斗机之一,成功拦截了大量V-1飞弹,也用于对地攻击。' },
  uk_mosquito: { name:'蚊式轰炸机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['rush'],
    desc:'木质结构的快速轰炸机,速度超过许多战斗机。',
    story:'蚊式轰炸机由德哈维兰公司研制,采用木质结构,速度极快,被德军飞行员称为“木制奇迹”。' },
  uk_beaufighter: { name:'英俊战士战斗机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    keywords:['stealth'],
    desc:'双发重型战斗机,专打德军夜间轰炸机。',
    story:'英俊战士是英国在二战中最重要的夜间战斗机之一,装备雷达,击落了大量德军夜间轰炸机。' },
  uk_halifax: { name:'哈利法克斯轰炸机', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'英国皇家空军的四发重型轰炸机。',
    story:'哈利法克斯是英国皇家空军的四发重型轰炸机,执行了对德国本土的战略轰炸任务。' },
  uk_stirling: { name:'斯特林轰炸机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'英国第一种四发重型轰炸机。',
    story:'斯特林是英国第一种四发重型轰炸机,载弹量大但飞行高度较低,容易受到德军夜间战斗机的攻击。' },
  uk_wellington: { name:'威灵顿轰炸机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'英国皇家空军的主力中型轰炸机。',
    story:'威灵顿轰炸机是英国在二战初期的主力轰炸机,以坚固的网状结构著称,能承受严重的战斗损伤。' },
  uk_gladiator: { name:'斗士战斗机', cost:2, atk:2, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'双翼战斗机,在北非和挪威作战。',
    story:'斗士是英国最后一种双翼战斗机,在战争初期参加了挪威和北非战役,性能已明显落后。' },
  uk_defiant: { name:'挑战者战斗机', cost:2, atk:2, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'炮塔战斗机,火力强但机动性差。',
    story:'挑战者是一种独特的炮塔战斗机,武器安装在动力炮塔上,火力强大但机动性差,在不列颠空战中损失惨重。' },
  uk_swordfish: { name:'剑鱼攻击机', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    keywords:['firststrike'],
    desc:'老式双翼鱼雷机,却击沉了俾斯麦号。',
    story:'剑鱼是英国海军的双翼鱼雷攻击机,虽然外形老旧,但在1940年塔兰托战役中重创意大利舰队,并参与击沉俾斯麦号。' },
  uk_barracuda: { name:'梭鱼轰炸机', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'舰载俯冲轰炸机,用于攻击提尔皮茨号。',
    story:'梭鱼是英国海军的舰载俯冲轰炸机,曾参与攻击德国战列舰提尔皮茨号。' },
  uk_sunderland: { name:'桑德兰水上飞机', cost:4, atk:3, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'远程水上巡逻机,猎杀德军潜艇。',
    story:'桑德兰水上飞机是英国皇家空军的远程巡逻机,在大西洋反潜战中发挥了重要作用,被德军潜艇称为“刺猬”。' },
  uk_beaufort: { name:'博福特鱼雷机', cost:3, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'鱼雷轰炸机,攻击德军运输船。',
    story:'博福特是英国皇家空军的鱼雷轰炸机,在英吉利海峡和北海攻击德军运输船。' },
  uk_meteor: { name:'流星喷气机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['rush'],
    desc:'英国第一种喷气式战斗机。',
    story:'流星是英国第一种喷气式战斗机,也是盟军唯一在二战中投入实战的喷气式战斗机,用于拦截V-1飞弹。' },
  uk_spitfire_mk9: { name:'喷火Mk IX', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['double'],
    desc:'喷火战斗机的改进型,与德军Fw 190抗衡。',
    story:'喷火Mk IX是喷火战斗机的重要改进型,专门用于对抗德军Fw 190战斗机,性能大幅提升。' },
  uk_hood: { name:'胡德号战列巡洋舰', cost:6, atk:6, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['guard'],
    desc:'皇家海军的骄傲,1941年被俾斯麦号击沉。',
    story:'胡德号是英国皇家海军最大的战列巡洋舰,1941年5月在丹麦海峡与俾斯麦号交战时被击中弹药库,瞬间爆炸沉没。' },
  uk_king_george_v: { name:'乔治五世国王号', cost:6, atk:6, hp:7, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['guard'],
    desc:'英国最新的战列舰,参与击沉俾斯麦号。',
    story:'乔治五世国王号是英国最新型的战列舰,装备14英寸主炮,1941年参与击沉德国战列舰俾斯麦号。' },
  uk_ark_royal: { name:'皇家方舟号航空母舰', cost:6, atk:5, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['guard'],
    desc:'皇家海军的功勋航母,参与击沉俾斯麦号。',
    story:'皇家方舟号是英国皇家海军最著名的航母之一,其舰载机发射的鱼雷卡住了俾斯麦号的舵机,最终导致其被击沉。' },
  uk_illustrious: { name:'光辉号航空母舰', cost:6, atk:5, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['guard'],
    desc:'装甲航母,塔兰托战役的主角。',
    story:'光辉号是英国皇家海军的装甲航母,1940年11月其舰载机突袭塔兰托港,重创意大利舰队。' },
  uk_belfast: { name:'贝尔法斯特号巡洋舰', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    desc:'英国皇家海军最著名的轻巡洋舰。',
    story:'贝尔法斯特号是英国皇家海军的轻巡洋舰,参加了北冰洋护航和诺曼底登陆,现保存于伦敦泰晤士河上。' },
  uk_rodney: { name:'罗德尼号战列舰', cost:6, atk:6, hp:7, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'纳尔逊级战列舰,参与击沉俾斯麦号。',
    story:'罗德尼号是英国纳尔逊级战列舰,1941年参与围歼德国战列舰俾斯麦号,以密集火力将其摧毁。' },
  uk_warspite: { name:'厌战号战列舰', cost:6, atk:6, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'uk',
    keywords:['guard'],
    desc:'皇家海军最功勋卓著的战列舰。',
    story:'厌战号是英国皇家海军最著名的战列舰之一,参加了两次世界大战,在二战中参加了纳尔维克海战和诺曼底登陆。' },
  uk_nelson: { name:'纳尔逊号战列舰', cost:6, atk:6, hp:7, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'装备三座三联装16英寸主炮的战列舰。',
    story:'纳尔逊号是英国皇家海军的战列舰,其独特之处在于三座主炮塔全部布置在舰桥前方。' },
  uk_formidable: { name:'可畏号航空母舰', cost:6, atk:5, hp:6, type:'unit', unitType:'ranged', rarity:'rare', nation:'uk',
    keywords:['guard'],
    desc:'装甲航母,参加马塔潘角海战。',
    story:'可畏号是英国皇家海军的装甲航母,1941年参加马塔潘角海战,其舰载机重创意大利舰队。' },
  uk_ajax: { name:'阿贾克斯号巡洋舰', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'uk',
    desc:'参加拉普拉塔河口海战的轻巡洋舰。',
    story:'阿贾克斯号是英国皇家海军的轻巡洋舰,1939年参加拉普拉塔河口海战,将德国袖珍战列舰斯佩伯爵号逼入绝境。' },
  uk_alanbrooke: { name:'阿兰布鲁克元帅', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +2/+2。',
    story:'阿兰布鲁克是英国帝国总参谋长,是丘吉尔最重要的军事顾问之一,在战略层面上对二战的胜利做出了重大贡献。' },
  uk_wavell: { name:'韦维尔将军', cost:4, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +2/+1。',
    story:'韦维尔将军在北非战场初期指挥英军击败意大利军队,后担任印度总督和东南亚盟军最高司令。' },
  uk_slim: { name:'斯利姆将军', cost:4, atk:0, hp:0, type:'command', rarity:'epic', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +2/+2。',
    story:'斯利姆将军指挥英国第14集团军在缅甸战场击败日军,被认为是最优秀的英军将领之一。' },
  uk_harris: { name:'哈里斯空军上将', cost:4, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:5 },
    desc:'作战令:点击敌方单位或敌方总部,造成 5 点伤害。',
    story:'哈里斯是英国皇家空军轰炸机司令部的指挥官,主导了对德国本土的大规模战略轰炸,绰号“轰炸机哈里斯”。' },
  uk_dowding: { name:'道丁空军上将', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:1, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +1/+2。',
    story:'道丁是英国皇家空军战斗机司令部的指挥官,在不列颠空战中指挥英军成功抵御德国空军的进攻。' },
  uk_operation_dynamo: { name:'发电机行动', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'heal_hq', value:6 },
    desc:'作战令:点击我方总部,恢复 6 点生命。',
    story:'“发电机行动”是1940年敦刻尔克大撤退的代号,英国动用一切可用船只,将33万英法军队撤回本土。' },
  uk_operation_husky: { name:'哈士奇行动', cost:4, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +2/+1。',
    story:'“哈士奇行动”是1943年盟军登陆西西里岛的代号,是盟军在欧洲战场的首次大规模两栖登陆。' },
  uk_operation_plunder: { name:'掠夺行动', cost:4, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:2 },
    desc:'作战令:点击我方总部,全体单位 +2/+2。',
    story:'“掠夺行动”是1945年盟军强渡莱茵河的行动代号,蒙哥马利指挥的英军和加拿大军队参加了这次作战。' },
  uk_churchill_speech: { name:'丘吉尔演讲', cost:3, atk:0, hp:0, type:'command', rarity:'epic', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:3, hp:1 },
    desc:'作战令:点击我方总部,全体单位 +3/+1。',
    story:'丘吉尔的演讲在二战中极大地鼓舞了英国人民的士气,他的“我们将在海滩上战斗”等演讲成为二战最著名的演说之一。' },
  uk_ultra: { name:'超级机密', cost:3, atk:0, hp:0, type:'command', rarity:'epic', nation:'uk',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:6 },
    desc:'作战令:点击敌方单位或敌方总部,造成 6 点伤害。',
    story:'“超级机密”是英国在二战中破译德军恩尼格玛密码的代号,为盟军提供了大量关键情报,对战争胜利起到了决定性作用。' },
  uk_bomber_offensive: { name:'轰炸机攻势', cost:5, atk:0, hp:0, type:'command', rarity:'epic', nation:'uk',
    target:'enemy_unit_or_hq', effect:{ type:'damage', value:7 },
    desc:'作战令:点击敌方单位或敌方总部,造成 7 点伤害。',
    story:'英国皇家空军轰炸机司令部对德国本土进行了持续的战略轰炸,虽然付出了惨重代价,但严重削弱了德国的战争工业。' },
  uk_desert_victory: { name:'沙漠胜利', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'buff_all', atk:2, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +2/+0。',
    story:'1942年阿拉曼战役的胜利扭转了北非战局,丘吉尔评价:“在阿拉曼之前,我们从未取得过胜利;在阿拉曼之后,我们从未遭遇过失败。”' },
  uk_atlantic_convoy: { name:'大西洋护航', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'heal_hq', value:7 },
    desc:'作战令:点击我方总部,恢复 7 点生命。',
    story:'大西洋护航是英国在二战中的生命线,皇家海军和皇家加拿大海军为商船队护航,与德军潜艇展开了长达数年的较量。' },
  uk_radar_network: { name:'雷达网络', cost:2, atk:0, hp:0, type:'command', rarity:'rare', nation:'uk',
    target:'player_hq', effect:{ type:'heal_hq', value:5 },
    desc:'作战令:点击我方总部,恢复 5 点生命。',
    story:'英国在二战前建立的雷达站网络“本土链”,为皇家空军提供了关键的预警信息,是不列颠空战胜利的重要因素。' },
  uk_home_defense: { name:'本土防御', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'uk',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:4 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 4 点。',
    story:'英国在二战中建立了完善的本土防御体系,包括国民自卫军、防空炮和拦阻气球,有效抵御了德军的空袭。' },
  uk_commando_raid: { name:'突击队突袭', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'uk',
    trigger:'enemy_deploy', effect:{ type:'damage_unit', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对该单位造成 4 点伤害。',
    story:'英国皇家突击队在二战中执行了多次突袭任务,包括袭击圣纳泽尔船坞和迪耶普登陆,给德军造成了不小的困扰。' },
  uk_night_raid: { name:'夜间空袭', cost:3, atk:0, hp:0, type:'counter', rarity:'rare', nation:'uk',
    trigger:'enemy_deploy', effect:{ type:'damage_hq', value:4 },
    desc:'应变:布下后,敌方部署单位时触发,对敌方总部造成 4 点伤害。',
    story:'英国皇家空军在二战中进行了大规模的夜间轰炸,虽然精度有限,但对德国城市和工业造成了严重破坏。' },
          /* ==================== 德国 · 老卡 ==================== */
  germany_tiger: { name:'虎式坦克', cost:6, atk:6, hp:7, type:'unit', unitType:'land', rarity:'legendary', nation:'germany',
    keywords:['guard'],
    desc:'德军最著名的重型坦克,盟军坦克手的噩梦。',
    story:'虎式坦克装备88毫米火炮和厚重装甲,在东西两线都给盟军和苏军造成重大威胁。' },
  germany_panzer_iv: { name:'四号坦克', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'德军装甲部队的中坚,产量最大的坦克。',
    story:'四号坦克是德军在二战中产量最大的坦克,从战争初期一直服役到战争结束。' },
  germany_panzer_iii: { name:'三号坦克', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德军早期装甲部队的主力。',
    story:'三号坦克是德军在战争初期的主力坦克,装备50毫米火炮,后逐渐被四号坦克和豹式坦克取代。' },
  germany_panther: { name:'豹式坦克', cost:5, atk:5, hp:6, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['firststrike'],
    desc:'综合性能最优秀的德军坦克。',
    story:'豹式坦克是德军在战争中期研制的中型坦克,综合了火力、装甲和机动性,被认为是二战中最优秀的坦克之一。' },
  germany_tiger_ii: { name:'虎王坦克', cost:7, atk:7, hp:8, type:'unit', unitType:'land', rarity:'legendary', nation:'germany',
    keywords:['guard'],
    desc:'德军最强大的重型坦克。',
    story:'虎王是德军在战争后期装备的重型坦克,装备88毫米长身管火炮,正面装甲厚度达150毫米。' },
  germany_bf109: { name:'Bf 109战斗机', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'德国空军的主力战斗机。',
    story:'Bf 109是德国空军在二战中的主力战斗机,产量超过三万架,从西班牙内战一直服役到战争结束。' },
  germany_fw190_old: { name:'Fw 190战斗机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'“百舌鸟”,德军最优秀的战斗机之一。',
    story:'Fw 190是德军在二战中最优秀的战斗机之一,火力强大,性能优异,给盟军造成重大威胁。' },
  germany_stuka: { name:'Ju 87斯图卡', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'俯冲轰炸机,尖啸声令人胆寒。',
    story:'Ju 87斯图卡俯冲轰炸机在俯冲时发出尖锐的啸声,被称为“耶利哥号角”,是德军闪击战的象征。' },
  germany_ju88_old: { name:'Ju 88轰炸机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'“万能轰炸机”,德军最通用的轰炸机。',
    story:'Ju 88是德军在二战中最通用的轰炸机,可执行水平轰炸、俯冲轰炸、夜间战斗和侦察等多种任务。' },
  germany_wehrmacht: { name:'国防军步兵', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德军的主力步兵部队。',
    story:'德国国防军是德军的主力部队,训练有素,纪律严明,是德军作战能力的重要基础。' },
  germany_volkssturm: { name:'国民突击队', cost:1, atk:1, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'战争末期由老人和少年组成的民兵。',
    story:'国民突击队是德军在战争末期组建的民兵组织,成员多为老人和少年,装备简陋但数量庞大。' },
  germany_fallschirmjager: { name:'空降猎兵', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['rush'],
    desc:'“绿色魔鬼”,德军空降部队。',
    story:'空降猎兵是德军的伞兵部队,绰号“绿色魔鬼”,在克里特岛空降作战中表现出色。' },
  germany_stug_iii: { name:'三号突击炮', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['guard'],
    desc:'德军最优秀的自行火炮之一。',
    story:'三号突击炮是德军在二战中最重要的自行火炮,产量超过一万辆,在防御作战中极为有效,被称为德军的“消防队”。' },
  germany_u_boat: { name:'U型潜艇', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    keywords:['stealth'],
    desc:'大西洋上的猎手,击沉大量盟军商船。',
    story:'U型潜艇是德军在大西洋海战中的主力,击沉了大量盟军商船,几乎切断了英国的海上生命线。' },
  germany_blitzkrieg: { name:'闪击战', cost:3, atk:0, hp:0, type:'command', rarity:'rare', nation:'germany',
    target:'player_hq', effect:{ type:'buff_all', atk:3, hp:0 },
    desc:'作战令:点击我方总部,全体单位 +3/+0。',
    story:'闪击战是德军在二战初期取得一系列胜利的核心战术,以坦克和飞机的快速协同突击为特点。' },
  germany_88_flak: { name:'88毫米高射炮', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    keywords:['firststrike'],
    desc:'既能防空又能反坦克的万能炮。',
    story:'88毫米高射炮是德军在二战中最著名的火炮,既能防空又能反坦克,在北非战场上给英军造成重大威胁。' },
  germany_mp40: { name:'MP40冲锋枪', cost:1, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德军步兵的标志性武器。',
    story:'MP40冲锋枪是德军在二战中广泛使用的冲锋枪,结构简单、可靠耐用,大量装备给装甲掷弹兵和伞兵。' },
  germany_stg44: { name:'StG 44突击步枪', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['rush'],
    desc:'世界上第一种大规模装备的突击步枪。',
    story:'StG 44是世界上第一种大规模装备的突击步枪,对战后突击步枪的发展产生了深远影响。' },
  germany_mg34: { name:'MG34机枪', cost:2, atk:3, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德军第一种通用机枪。',
    story:'MG34是德军在二战中使用的通用机枪,射速高、可靠性好,是德军步兵班组的重要支援武器。' },
  germany_panzerfaust_old: { name:'铁拳', cost:2, atk:3, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德军步兵的反坦克武器。',
    story:'铁拳是德军在战争后期广泛使用的反坦克武器,结构简单、威力大,大量装备给国民突击队和正规军。' },
  germany_flak36: { name:'Flak 36高射炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'中口径防空炮。',
    story:'Flak 36 37毫米高射炮是德军的中口径防空武器,也能用于对付轻型坦克。' },
  germany_sturmgeschutz: { name:'突击炮', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德军步兵支援火力。',
    story:'三号突击炮是德军在二战中最重要的自行火炮,广泛装备于突击炮营,在防御作战中极为有效。' },
  germany_sdkfz251: { name:'Sd.Kfz. 251半履带车', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    keywords:['mobile'],
    desc:'德军装甲掷弹兵的输送车。',
    story:'Sd.Kfz. 251半履带装甲车是德军装甲掷弹兵的主要输送工具,也改装为多种支援车型。' },
  germany_panzer_ii: { name:'二号坦克', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    keywords:['mobile'],
    desc:'德军早期轻型坦克。',
    story:'二号坦克是德军在战争初期的轻型坦克,装备20毫米机关炮,主要用于侦察和支援步兵。' },
  germany_panzer_38t: { name:'38(t)坦克', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'来自捷克的优秀轻型坦克。',
    story:'38(t)坦克是德军在吞并捷克斯洛伐克后获得的优秀轻型坦克,在战争初期发挥了重要作用。' },
  germany_nashorn: { name:'犀牛坦克歼击车', cost:4, atk:5, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['firststrike'],
    desc:'装备88毫米火炮的敞开式坦克歼击车。',
    story:'犀牛坦克歼击车装备88毫米长身管火炮,火力强悍但防护薄弱,主要用于远程反坦克作战。' },
  germany_hornisse: { name:'黄蜂坦克歼击车', cost:4, atk:5, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['firststrike'],
    desc:'与犀牛同型的坦克歼击车。',
    story:'黄蜂坦克歼击车与犀牛同型,装备88毫米火炮,是德军在战争中期的重要反坦克武器。' },
  germany_mobelhwagen: { name:'装甲列车', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在铁路上机动的装甲列车。',
    story:'德军在二战中使用了多列装甲列车,主要用于东线后方的反游击作战和铁路保护。' },
  germany_e_boat: { name:'S艇鱼雷快艇', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    keywords:['rush'],
    desc:'德军快速鱼雷艇。',
    story:'S艇是德军在二战中的快速鱼雷艇,在英吉利海峡和北海攻击盟军船只。' },
  germany_bismarck: { name:'俾斯麦号战列舰', cost:7, atk:6, hp:8, type:'unit', unitType:'ranged', rarity:'legendary', nation:'germany',
    keywords:['guard'],
    desc:'德国海军最著名的战列舰。',
    story:'俾斯麦号是德国海军在二战中最著名的战列舰,1941年击沉英国胡德号,后被英国皇家海军围歼。' },
  germany_scharnhorst: { name:'沙恩霍斯特号战列舰', cost:6, atk:6, hp:6, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    keywords:['mobile'],
    desc:'德国海军的战列巡洋舰。',
    story:'沙恩霍斯特号是德国海军的战列巡洋舰,1943年在北角海战中被英国皇家海军击沉。' },
  germany_prinz_eugen_ship: { name:'欧根亲王号重巡洋舰', cost:5, atk:5, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'德国海军重巡洋舰。',
    story:'欧根亲王号是德国海军的重巡洋舰,曾与俾斯麦号一起执行任务,战后被移交给美国。' },
  germany_scorched_earth: { name:'焦土政策', cost:2, atk:0, hp:0, type:'counter', rarity:'rare', nation:'germany',
    trigger:'enemy_attack_hq', effect:{ type:'reduce_damage', value:4 },
    desc:'应变:布下后,敌方攻击我方总部时触发,本次伤害减少 4 点。',
    story:'德军在撤退时实施焦土政策,破坏一切可能被敌军利用的设施和物资。' },
      /* ==================== 德国 · 新增卡牌(100 张) ==================== */
  germany_1st_panzer: { name:'第1装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['guard'],
    desc:'德军最早的装甲师之一,从波兰一路打到东线。',
    story:'第1装甲师是德军最早的装甲师之一,参加了波兰、法国和苏联战场的作战,是德军装甲部队的中坚。' },
  germany_2nd_panzer: { name:'第2装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'在法国和东线作战的德军装甲师。',
    story:'第2装甲师参加了从波兰到东线的一系列作战,在库尔斯克会战和诺曼底战役中都有重要表现。' },
  germany_3rd_panzer: { name:'第3装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'“熊师”,在东线作战的德军装甲部队。',
    story:'第3装甲师绰号“熊师”,参加了波兰、法国和苏联战场的作战,在库尔斯克会战中损失惨重。' },
  germany_4th_panzer: { name:'第4装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第4装甲师参加了波兰、法国和苏联战场的作战,是德军装甲部队的老牌部队之一。' },
  germany_5th_panzer: { name:'第5装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在北非和东线作战的德军装甲师。',
    story:'第5装甲师参加了巴尔干战役和东线作战,在库尔斯克会战中损失惨重。' },
  germany_6th_panzer: { name:'第6装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第6装甲师参加了法国战役和东线作战,在库尔斯克会战中与苏军展开激烈坦克战。' },
  germany_7th_panzer: { name:'第7装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['rush'],
    desc:'“幽灵师”,隆美尔曾指挥过的装甲师。',
    story:'第7装甲师绰号“幽灵师”,在隆美尔指挥下于法国战役中以惊人速度推进,被称为“幽灵师”。' },
  germany_8th_panzer: { name:'第8装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第8装甲师参加了巴尔干战役和东线作战,在库尔斯克会战后参加了多次防御作战。' },
  germany_9th_panzer: { name:'第9装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第9装甲师参加了法国战役和东线作战,在库尔斯克会战中损失惨重。' },
  germany_10th_panzer: { name:'第10装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在北非和东线作战的德军装甲师。',
    story:'第10装甲师参加了波兰、法国和北非战役,在突尼斯战役中全军覆没,后重建参加东线作战。' },
  germany_11th_panzer: { name:'第11装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'“幽灵师”,在东线作战的德军装甲师。',
    story:'第11装甲师参加了巴尔干战役和东线作战,在库尔斯克会战中与苏军展开激烈战斗。' },
  germany_12th_panzer: { name:'第12装甲师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第12装甲师参加了东线作战,在库尔斯克会战后参加了多次防御作战。' },
  germany_13th_panzer: { name:'第13装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在巴尔干和东线作战的德军装甲师。',
    story:'第13装甲师参加了巴尔干战役和东线作战,在库尔斯克会战中损失惨重。' },
  germany_14th_panzer: { name:'第14装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第14装甲师参加了巴尔干战役和东线作战,在斯大林格勒战役中被围歼,后重建参加西西里战役。' },
  germany_15th_panzer: { name:'第15装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在北非和意大利作战的德军装甲师。',
    story:'第15装甲师是隆美尔非洲军团的主力部队之一,在突尼斯战役中全军覆没,后重建参加意大利战役。' },
  germany_16th_panzer: { name:'第16装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第16装甲师参加了法国战役和东线作战,在斯大林格勒战役中被围歼,后重建。' },
  germany_17th_panzer: { name:'第17装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第17装甲师参加了东线作战,在库尔斯克会战后参加了多次防御作战。' },
  germany_21st_panzer: { name:'第21装甲师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['rush'],
    desc:'北非战场上的德军装甲师,诺曼底反击的主力。',
    story:'第21装甲师是隆美尔非洲军团的主力部队之一,1944年诺曼底登陆日当天发起反击,一度推进到海边。' },
  germany_23rd_panzer: { name:'第23装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第23装甲师参加了东线作战,在库尔斯克会战后参加了多次防御作战。' },
  germany_24th_panzer: { name:'第24装甲师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'在东线作战的德军装甲师。',
    story:'第24装甲师参加了东线作战,在斯大林格勒战役中被围歼,后重建。' },
  germany_army_group_center: { name:'中央集团军群', cost:5, atk:5, hp:6, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['guard'],
    desc:'德军东线三大集团军群之一,负责中路进攻。',
    story:'中央集团军群是德军东线三大集团军群之一,负责莫斯科方向的进攻,1944年在巴格拉季昂行动中被苏军彻底击溃。' },
  germany_army_group_south: { name:'南方集团军群', cost:5, atk:5, hp:6, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['guard'],
    desc:'德军东线三大集团军群之一,负责南线进攻。',
    story:'南方集团军群是德军东线三大集团军群之一,负责乌克兰和南俄方向的进攻,在斯大林格勒和库尔斯克战役中遭受重创。' },
  germany_army_group_north: { name:'北方集团军群', cost:4, atk:4, hp:6, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'德军东线三大集团军群之一,围攻列宁格勒。',
    story:'北方集团军群是德军东线三大集团军群之一,负责波罗的海方向和列宁格勒的围攻,围城长达872天。' },
  germany_afrika_korps: { name:'非洲军团', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['mobile'],
    desc:'隆美尔指挥的北非德军精锐。',
    story:'非洲军团是德军在北非战场的精锐部队,由隆美尔指挥,以出色的战术和机动能力多次击败英军。' },
  germany_gebirgsjager: { name:'山地猎兵', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['mobile'],
    desc:'德军山地作战部队,攀登高加索山峰。',
    story:'德军山地猎兵是专门训练的山地作战部队,1942年曾攀登高加索山脉的厄尔布鲁士峰,插上德军旗帜。' },
  germany_fallschirm_pioneer: { name:'空降工兵', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['rush'],
    desc:'空降部队中的工兵,负责摧毁关键目标。',
    story:'德军空降工兵在克里特岛战役中负责夺取机场和关键目标,表现出色。' },
  germany_feldgendarmerie: { name:'宪兵队', cost:2, atk:2, hp:2, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德军军事警察,负责维持军纪。',
    story:'德军宪兵队负责维持军纪和指挥交通,在占领区也执行镇压任务。' },
  germany_grenadier: { name:'装甲掷弹兵', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'伴随坦克作战的机械化步兵。',
    story:'装甲掷弹兵是德军的机械化步兵,通常乘坐半履带装甲车伴随坦克作战,是德军装甲部队的重要组成部分。' },
  germany_panzergrenadier: { name:'装甲掷弹兵营', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德军装甲师中的精锐步兵。',
    story:'装甲掷弹兵营是德军装甲师中的精锐步兵部队,装备精良,训练有素,与坦克密切协同作战。' },
  germany_pioneer: { name:'工兵营', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'负责突破障碍和构筑工事的工程部队。',
    story:'德军工兵在突破敌方阵地时承担开路任务,也负责构筑防御工事和架设桥梁。' },
  germany_sturmpionier: { name:'突击工兵', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'携带炸药和火焰喷射器的攻坚部队。',
    story:'德军突击工兵是专门用于攻坚的部队,携带炸药包和火焰喷射器,负责摧毁敌方坚固工事。' },
  germany_sniper: { name:'狙击手', cost:2, atk:4, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    keywords:['stealth'],
    desc:'隐藏在暗处的射手,狙杀敌方军官。',
    story:'德军狙击手训练有素,在东西两线都给盟军和苏军造成不小的威胁,优先狙杀军官和通信兵。' },
  germany_mg42_team: { name:'MG42机枪组', cost:3, atk:4, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['guard'],
    desc:'“希特勒的电锯”,射速极高的通用机枪。',
    story:'MG42通用机枪以其极高的射速著称,每分钟可发射1200发子弹,被盟军士兵称为“希特勒的电锯”。' },
  germany_panzerfaust: { name:'铁拳反坦克手', cost:2, atk:3, hp:1, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'手持铁拳火箭筒的步兵,近距离反坦克。',
    story:'“铁拳”是德军在战争后期广泛使用的反坦克武器,结构简单、威力大,大量装备给国民突击队和正规军。' },
  germany_panzerschreck: { name:'坦克杀手', cost:3, atk:4, hp:1, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['firststrike'],
    desc:'装备坦克杀手火箭筒的反坦克兵。',
    story:'“坦克杀手”是德军仿制美国巴祖卡研制的反坦克火箭筒,口径更大,威力更强。' },
  germany_volksgrenadier: { name:'国民掷弹兵', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'战争后期组建的步兵师,装备较差但数量庞大。',
    story:'国民掷弹兵师是德军在战争后期组建的步兵师,兵员多为新兵和恢复的伤员,装备较差但数量庞大。' },
  germany_luftwaffe_field: { name:'空军野战师', cost:2, atk:2, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'由空军人员组成的地面部队。',
    story:'空军野战师是戈林将多余的空军人员改编而成的地面部队,缺乏陆军作战经验,战斗力较弱。' },
  germany_kriegsmarine_inf: { name:'海军步兵', cost:3, atk:3, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'由海军人员组成的地面作战部队。',
    story:'战争后期,德国海军将部分人员改编为地面作战部队,参加了柏林等地的防御作战。' },
  germany_hitlerjugend: { name:'希特勒青年团', cost:2, atk:3, hp:2, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['rush'],
    desc:'由青年团成员组成的武装党卫军师。',
    story:'希特勒青年团师由青年团志愿者组成,1944年在诺曼底与盟军激战,表现出极高的战斗意志。' },
  germany_ss_hitlerjugend: { name:'党卫军青年师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['rush'],
    desc:'武装党卫军中最年轻的师,作战极为顽强。',
    story:'党卫军第12“希特勒青年团”装甲师由青年团志愿者组成,在诺曼底和突出部战役中表现出色,伤亡极为惨重。' },
  germany_ss_das_reich: { name:'党卫军帝国师', cost:6, atk:6, hp:6, type:'unit', unitType:'land', rarity:'legendary', nation:'germany',
    keywords:['rush'],
    desc:'武装党卫军最精锐的装甲师之一。',
    story:'“帝国”师是武装党卫军的精锐装甲师,参加了从法国到东线的一系列重大作战,在库尔斯克会战中损失惨重。' },
  germany_ss_totenkopf: { name:'党卫军骷髅师', cost:6, atk:6, hp:6, type:'unit', unitType:'land', rarity:'legendary', nation:'germany',
    keywords:['guard'],
    desc:'以骷髅为标志的党卫军装甲师。',
    story:'“骷髅”师是武装党卫军的精锐装甲师,参加了东线的多次重大作战,以凶悍的作战风格著称。' },
  germany_ss_wiking: { name:'党卫军维京师', cost:5, atk:5, hp:6, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['guard'],
    desc:'由北欧志愿者组成的党卫军师。',
    story:'“维京”师是武装党卫军中的外籍志愿者师,成员来自北欧各国,在东线作战中表现出色。' },
  germany_ss_hohenstaufen: { name:'党卫军霍恩施陶芬师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['mobile'],
    desc:'党卫军第9装甲师,在东西两线作战。',
    story:'霍恩施陶芬师是武装党卫军的装甲师,参加了诺曼底、市场花园和阿登战役等一系列作战。' },
  germany_ss_frundsberg: { name:'党卫军弗伦茨贝格师', cost:5, atk:5, hp:5, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['mobile'],
    desc:'党卫军第10装甲师,在东西两线作战。',
    story:'弗伦茨贝格师是武装党卫军的装甲师,参加了诺曼底和东线的作战。' },
  germany_ss_nord: { name:'党卫军北方师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'党卫军山地师,在北极圈作战。',
    story:'“北方”师是武装党卫军的一个山地师,在芬兰和挪威的北极圈地区作战。' },
  germany_ss_prinz_eugen: { name:'党卫军欧根亲王师', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'党卫军山地师,在巴尔干作战。',
    story:'“欧根亲王”师是武装党卫军的山地师,主要在巴尔干地区执行反游击作战。' },
  germany_ss_handschar: { name:'党卫军弯刀师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'由波斯尼亚穆斯林组成的党卫军师。',
    story:'“弯刀”师是武装党卫军中的一个由波斯尼亚穆斯林组成的师,主要在巴尔干地区作战。' },
  germany_ss_charlemagne: { name:'党卫军查理曼师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['guard'],
    desc:'由法国志愿者组成的党卫军师。',
    story:'“查理曼”师由法国志愿者组成,1945年在柏林战役中作为最后守卫者之一与苏军作战。' },
  germany_ss_wallonien: { name:'党卫军瓦隆人师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'由比利时瓦隆志愿者组成的党卫军部队。',
    story:'“瓦隆人”师由比利时瓦隆志愿者组成,在东线作战中表现出色,是德军外籍部队中最顽强的之一。' },
  germany_ss_langemarck: { name:'党卫军朗格马克师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'由比利时佛兰芒志愿者组成的党卫军部队。',
    story:'“朗格马克”师由比利时佛兰芒志愿者组成,在东线作战中表现出色。' },
  germany_ss_nederland: { name:'党卫军荷兰师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'由荷兰志愿者组成的党卫军部队。',
    story:'“荷兰”师由荷兰志愿者组成,在东线作战中表现出色。' },
  germany_heer_infantry: { name:'国防军步兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'德国国防军的标准步兵师。',
    story:'国防军步兵师是德军的主力部队,训练有素,纪律严明,是德军作战能力的重要基础。' },
  germany_jaeger: { name:'猎兵师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    keywords:['mobile'],
    desc:'德军轻装步兵师,机动性强。',
    story:'德军猎兵师是轻装步兵师,装备较轻、机动性较强,适合在复杂地形中作战。' },
  germany_leichte_division: { name:'轻装师', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    keywords:['mobile'],
    desc:'德军在北非的轻装部队。',
    story:'德军轻装师是专门为北非战场组建的部队,装备较轻、机动性强,是非洲军团的重要组成部分。' },
  germany_luftlande: { name:'空降猎兵', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['rush'],
    desc:'“绿色魔鬼”,德军空降部队。',
    story:'空降猎兵是德军的伞兵部队,绰号“绿色魔鬼”,在克里特岛空降作战中表现出色。' },
  germany_ramcke_brigade: { name:'拉姆克旅', cost:4, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'北非战场上的德军空降旅。',
    story:'拉姆克旅是德军在北非战场上的空降旅,参加了阿拉曼战役,后徒步撤退到突尼斯。' },
  germany_kampfgruppe: { name:'战斗群', cost:3, atk:3, hp:4, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    desc:'由多兵种临时编组的作战单位。',
    story:'战斗群是德军在战争后期常用的临时编组作战单位,由步兵、装甲兵和炮兵混编,灵活应对战场需要。' },
  germany_panzer_jaeger: { name:'装甲猎兵', cost:3, atk:4, hp:3, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['firststrike'],
    desc:'德军坦克歼击车部队的步兵。',
    story:'装甲猎兵是德军坦克歼击车部队的士兵,装备坦克歼击车或反坦克炮,专门猎杀敌军坦克。' },
  germany_sturmgeschutz_brigade: { name:'突击炮旅', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['guard'],
    desc:'装备三号突击炮的独立旅。',
    story:'突击炮旅是德军装备三号突击炮的独立作战单位,在防御作战中极为有效,是德军的“消防队”。' },
  germany_heavy_panzer: { name:'重装甲营', cost:6, atk:6, hp:7, type:'unit', unitType:'land', rarity:'legendary', nation:'germany',
    keywords:['guard'],
    desc:'装备虎式坦克的独立重装甲营。',
    story:'重装甲营是德军装备虎式坦克的独立作战单位,在东西两线都给盟军和苏军造成重大威胁。' },
  germany_schwere_panzer: { name:'虎式重装甲营', cost:6, atk:6, hp:7, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['guard'],
    desc:'专门装备虎式坦克的独立重装甲营。',
    story:'虎式重装甲营是德军专门装备虎式坦克的独立单位,在战场上以强大的火力和装甲著称。' },
  germany_tiger_battalion: { name:'虎式坦克营', cost:6, atk:6, hp:7, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['guard'],
    desc:'虎式坦克的作战单位。',
    story:'虎式坦克营是德军装备虎式坦克的作战单位,在库尔斯克会战中首次大规模参战。' },
  germany_panther_battalion: { name:'豹式坦克营', cost:5, atk:5, hp:6, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    desc:'装备豹式坦克的装甲营。',
    story:'豹式坦克营是德军装备豹式坦克的作战单位,在库尔斯克会战中首次参战,性能优异但初期故障频发。' },
  germany_hetzer: { name:'追猎者坦克歼击车', cost:3, atk:4, hp:4, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['firststrike'],
    desc:'基于38(t)底盘的小型坦克歼击车。',
    story:'追猎者是以38(t)坦克为底盘改装的轻型坦克歼击车,装备75毫米火炮,外形低矮,易于隐蔽。' },
  germany_jagdpanther: { name:'猎豹坦克歼击车', cost:6, atk:6, hp:6, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    keywords:['firststrike'],
    desc:'以豹式坦克为底盘的重型坦克歼击车。',
    story:'猎豹是以豹式坦克为底盘的重型坦克歼击车,装备88毫米长身管火炮,是二战中最优秀的坦克歼击车之一。' },
  germany_jagdtiger: { name:'猎虎坦克歼击车', cost:7, atk:7, hp:7, type:'unit', unitType:'land', rarity:'legendary', nation:'germany',
    keywords:['firststrike'],
    desc:'以虎王为底盘,装备128毫米火炮的巨型歼击车。',
    story:'猎虎是以虎王坦克为底盘的重型坦克歼击车,装备128毫米火炮,是二战中威力最大的装甲车辆之一,但重量过大机动性差。' },
  germany_jagdpanzer_iv: { name:'四号坦克歼击车', cost:4, atk:4, hp:5, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['firststrike'],
    desc:'以四号坦克为底盘的坦克歼击车。',
    story:'四号坦克歼击车是以四号坦克为底盘改装的坦克歼击车,装备75毫米火炮,外形低矮,易于隐蔽。' },
  germany_marder: { name:'黄鼠狼坦克歼击车', cost:3, atk:4, hp:3, type:'unit', unitType:'land', rarity:'common', nation:'germany',
    keywords:['firststrike'],
    desc:'以坦克底盘改装的敞开式坦克歼击车。',
    story:'黄鼠狼是以各种坦克底盘改装的敞开式坦克歼击车,装备75毫米或88毫米火炮,防护薄弱但火力凶悍。' },
  germany_wespe: { name:'黄蜂自行火炮', cost:3, atk:3, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'装备105毫米榴弹炮的自行火炮。',
    story:'黄蜂是以二号坦克为底盘的自行火炮,装备105毫米榴弹炮,是德军主要的自行火炮之一。' },
  germany_hummel: { name:'野蜂自行火炮', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'装备150毫米榴弹炮的自行火炮。',
    story:'野蜂是以四号坦克为底盘的自行火炮,装备150毫米榴弹炮,是德军重要的重型自行火炮。' },
  germany_brummbar: { name:'灰熊突击坦克', cost:4, atk:5, hp:6, type:'unit', unitType:'land', rarity:'rare', nation:'germany',
    keywords:['guard'],
    desc:'装备150毫米榴弹炮的突击坦克。',
    story:'灰熊是以四号坦克为底盘改装的突击坦克,装备150毫米榴弹炮,专门用于摧毁城市和筑垒工事。' },
  germany_sturmtiger: { name:'突击虎', cost:6, atk:7, hp:6, type:'unit', unitType:'land', rarity:'epic', nation:'germany',
    desc:'装备380毫米臼炮的巨型突击炮。',
    story:'突击虎是以虎式坦克为底盘的突击炮,装备380毫米臼炮,发射的火箭弹能摧毁整个街区,但产量极少。' },
  germany_karl_mortar: { name:'卡尔臼炮', cost:7, atk:8, hp:5, type:'unit', unitType:'ranged', rarity:'legendary', nation:'germany',
    desc:'口径达600毫米的巨型攻城炮。',
    story:'卡尔臼炮是德军用于攻击坚固工事的巨型臼炮,口径达600毫米,参加了塞瓦斯托波尔和華沙起义的作战。' },
  germany_lefh18: { name:'105毫米榴弹炮', cost:3, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'德军师属火炮,性能优秀。',
    story:'leFH 18 105毫米榴弹炮是德军步兵师的标准师属火炮,性能优秀,广泛用于东西两线。' },
  germany_sfh18: { name:'150毫米重型榴弹炮', cost:5, atk:6, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'德军重型野战炮,威力强大。',
    story:'sFH 18 150毫米重型榴弹炮是德军军级炮兵的主力火炮,威力强大,是德军重要的支援火力。' },
  germany_nebelwerfer: { name:'六管火箭炮', cost:4, atk:5, hp:2, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'“尖叫的米莉”,德军的火箭炮。',
    story:'Nebelwerfer 41六管火箭炮发射时发出凄厉的尖啸声,被盟军称为“尖叫的米莉”。' },
  germany_panzerwerfer: { name:'装甲火箭炮', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    keywords:['mobile'],
    desc:'以半履带车为底盘的火箭炮。',
    story:'装甲火箭炮是以半履带车为底盘改装的火箭炮,装备十管火箭发射器,机动性较牵引式火箭炮好。' },
  germany_88_pak43: { name:'88毫米PaK 43', cost:4, atk:5, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    keywords:['firststrike'],
    desc:'88毫米长身管反坦克炮,威力惊人。',
    story:'PaK 43是88毫米高射炮的反坦克型号,采用长身管设计,穿甲能力极强,能击穿任何盟军坦克。' },
  germany_75_pak40: { name:'75毫米PaK 40', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'德军后期的主力反坦克炮。',
    story:'PaK 40 75毫米反坦克炮是德军在战争后期的主力反坦克炮,能击穿大多数盟军坦克的正面装甲。' },
  germany_20mm_flak: { name:'20毫米高射炮', cost:2, atk:3, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'四管高射炮,对低空目标效果显著。',
    story:'Flak 38四管20毫米高射炮是德军重要的低空防空武器,也常用于对地攻击。' },
  germany_37mm_flak: { name:'37毫米高射炮', cost:3, atk:4, hp:2, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'中口径防空炮,也能反坦克。',
    story:'Flak 36 37毫米高射炮是德军的中口径防空武器,也能用于对付轻型坦克。' },
  germany_128mm_flak: { name:'128毫米高射炮', cost:5, atk:6, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    desc:'德军最大的防空炮,也用于反坦克。',
    story:'Flak 40 128毫米高射炮是德军最大的防空火炮,部署在本土防空塔上,也能用于反坦克作战。' },
  germany_me262: { name:'Me 262喷气机', cost:6, atk:6, hp:4, type:'unit', unitType:'ranged', rarity:'legendary', nation:'germany',
    keywords:['double'],
    desc:'世界上第一种投入实战的喷气式战斗机。',
    story:'Me 262是世界上第一种投入实战的喷气式战斗机,速度远超盟军活塞战斗机,但投产太晚,未能改变战局。' },
  germany_me163: { name:'Me 163彗星', cost:4, atk:5, hp:2, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    keywords:['rush'],
    desc:'火箭动力拦截机,速度极快但燃料危险。',
    story:'Me 163“彗星”是火箭动力拦截机,速度极快但燃料极易爆炸,作战时间只有几分钟。' },
  germany_ar234: { name:'Ar 234喷气轰炸机', cost:6, atk:6, hp:3, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    keywords:['rush'],
    desc:'世界上第一种喷气式轰炸机。',
    story:'Ar 234是世界上第一种喷气式轰炸机,速度极快,主要用于侦察和轰炸,产量有限。' },
  germany_he162: { name:'He 162喷气机', cost:4, atk:4, hp:3, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'“国民战斗机”,紧急研制的喷气机。',
    story:'He 162是德国在战争末期紧急研制的“国民战斗机”,采用木质结构,希望能大量生产,但性能不佳。' },
  germany_fw190: { name:'Fw 190战斗机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    desc:'“百舌鸟”,德军最优秀的战斗机之一。',
    story:'Fw 190“百舌鸟”是德军在二战中最优秀的战斗机之一,火力强大,性能优异,给盟军造成重大威胁。' },
  germany_ta152: { name:'Ta 152高空战斗机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    desc:'Fw 190的高空改进型。',
    story:'Ta 152是Fw 190的高空改进型,专门用于对付盟军的高空轰炸机,但产量极少。' },
  germany_ju88: { name:'Ju 88轰炸机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'“万能轰炸机”,德军最通用的轰炸机。',
    story:'Ju 88是德军在二战中最通用的轰炸机,可执行水平轰炸、俯冲轰炸、夜间战斗和侦察等多种任务。' },
  germany_he111: { name:'He 111轰炸机', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'德军早期中型轰炸机,参加不列颠空战。',
    story:'He 111是德军在战争初期的主力中型轰炸机,参加了西班牙内战和不列颠空战,后主要用作运输机。' },
  germany_do217: { name:'Do 217轰炸机', cost:5, atk:5, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'德军双发轰炸机,能携带滑翔炸弹。',
    story:'Do 217是德军在战争中期使用的双发轰炸机,能携带滑翔炸弹攻击舰船。' },
  germany_fw200: { name:'Fw 200秃鹰', cost:4, atk:4, hp:4, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'远程海上巡逻机,猎杀盟军商船。',
    story:'Fw 200“秃鹰”是德军远程海上巡逻机,在大西洋上猎杀盟军商船,给英国海运造成重大威胁。' },
  germany_bv138: { name:'BV 138水上飞机', cost:4, atk:3, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'远程水上侦察机。',
    story:'BV 138是德军远程水上侦察机,在大西洋和北冰洋执行巡逻任务。' },
  germany_ju52: { name:'Ju 52运输机', cost:3, atk:1, hp:4, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'德军主力运输机,空投伞兵和物资。',
    story:'Ju 52是德军在二战中的主力运输机,采用三发设计,参加了克里特岛空降作战和斯大林格勒空运。' },
  germany_me323: { name:'Me 323巨人运输机', cost:5, atk:2, hp:5, type:'unit', unitType:'ranged', rarity:'rare', nation:'germany',
    desc:'巨型运输机,能运载坦克和重炮。',
    story:'Me 323“巨人”是德军最大的运输机,六发设计,能运载坦克和重型装备,但速度慢、防护薄弱。' },
  germany_go242: { name:'Go 242滑翔机', cost:3, atk:2, hp:3, type:'unit', unitType:'ranged', rarity:'common', nation:'germany',
    desc:'重型滑翔机,用于运输物资。',
    story:'Go 242是德军在二战中使用的中型滑翔机,能运载车辆和物资,主要用于北非和东线。' },
  germany_v1: { name:'V-1飞弹', cost:5, atk:6, hp:2, type:'unit', unitType:'ranged', rarity:'epic', nation:'germany',
    keywords:['rush'],
    desc:'世界上第一种巡航导弹。',
    story:'V-1飞弹是世界上第一种投入实战的巡航导弹,从法国和荷兰发射袭击伦敦,飞行时发出独特的声音,被称为“嗡嗡炸弹”。' },
  germany_king_tiger: { name:'虎王重型坦克', cost:7, atk:7, hp:8, type:'unit', unitType:'land', rarity:'legendary', nation:'germany',
    keywords:['guard'],
    desc:'德军最强大的重型坦克。',
    story:'虎王是德军在战争后期装备的重型坦克,装备88毫米长身管火炮,正面装甲厚度达150毫米,但机动性差、机械故障频繁。' },
  germany_maus: { name:'鼠式超重型坦克', cost:8, atk:8, hp:10, type:'unit', unitType:'land', rarity:'legendary', nation:'germany',
    keywords:['guard'],
    desc:'重达188吨的超重型坦克,仅有样车。',
    story:'鼠式是德军研制的超重型坦克,重达188吨,装备128毫米主炮和75毫米副炮,但仅生产了两辆样车,从未参战。' },
      /* ==================== 总部牌(25 张) ==================== */
  hq_germany_berlin: { name:'柏林', type:'hq', hp:20, rarity:'epic', nation:'germany',
    desc:'德意志第三帝国的首都,战争末期被苏军攻占。',
    story:'柏林是纳粹德国的首都,1945年4月苏军发动柏林战役,经过激烈巷战最终攻占该城。' },
  hq_germany_ruhr: { name:'鲁尔工业区', type:'hq', hp:20, rarity:'rare', nation:'germany',
    desc:'德国最重要的工业区,为德军提供大量武器装备。',
    story:'鲁尔工业区是德国最重要的重工业基地,为德军提供了大量武器弹药,是盟军战略轰炸的重点目标。' },
  hq_germany_hamburg: { name:'汉堡', type:'hq', hp:20, rarity:'rare', nation:'germany',
    desc:'德国最大的港口城市。',
    story:'汉堡是德国最大的港口城市,1943年盟军的轰炸引发大火风暴,造成严重破坏。' },
  hq_germany_munich: { name:'慕尼黑', type:'hq', hp:20, rarity:'rare', nation:'germany',
    desc:'纳粹党的发源地。',
    story:'慕尼黑是纳粹党的发源地,1938年《慕尼黑协定》在此签订,是纳粹德国扩张的重要标志。' },
  hq_germany_konigsberg: { name:'柯尼斯堡', type:'hq', hp:20, rarity:'common', nation:'germany',
    desc:'东普鲁士的首府。',
    story:'柯尼斯堡是东普鲁士的首府,1945年被苏军攻占,战后成为苏联的加里宁格勒。' },
  hq_usa_dc: { name:'华盛顿', type:'hq', hp:20, rarity:'epic', nation:'usa',
    desc:'美利坚合众国的首都。',
    story:'华盛顿是美国的首都,二战期间是美国政治和军事决策的中心。' },
  hq_usa_ny: { name:'纽约', type:'hq', hp:20, rarity:'rare', nation:'usa',
    desc:'美国最大的城市和港口。',
    story:'纽约是美国最大的城市和港口,二战期间是美军物资运输的重要枢纽。' },
  hq_usa_detroit: { name:'底特律', type:'hq', hp:20, rarity:'rare', nation:'usa',
    desc:'美国的汽车工业中心,战时转产坦克和飞机。',
    story:'底特律是美国的汽车工业中心,二战期间转产坦克、飞机和军用车辆,被称为“民主国家的兵工厂”。' },
  hq_usa_pearl: { name:'珍珠港', type:'hq', hp:20, rarity:'epic', nation:'usa',
    desc:'美国太平洋舰队的主要基地。',
    story:'珍珠港是美国太平洋舰队的主要基地,1941年12月7日遭到日军偷袭,美国由此正式参战。' },
  hq_usa_westpoint: { name:'西点军校', type:'hq', hp:20, rarity:'rare', nation:'usa',
    desc:'美国最著名的军事学院。',
    story:'西点军校是美国最著名的军事学院,培养了艾森豪威尔、巴顿、麦克阿瑟等众多二战名将。' },
  hq_japan_tokyo: { name:'东京', type:'hq', hp:20, rarity:'epic', nation:'japan',
    desc:'日本帝国的首都。',
    story:'东京是日本帝国的首都,战争后期遭到美军大规模轰炸,1945年8月日本在此宣布投降。' },
  hq_japan_yokosuka: { name:'横须贺', type:'hq', hp:20, rarity:'rare', nation:'japan',
    desc:'日本海军最重要的军港。',
    story:'横须贺是日本海军最重要的军港,联合舰队的主力舰艇多以此为母港。' },
  hq_japan_osaka: { name:'大阪', type:'hq', hp:20, rarity:'rare', nation:'japan',
    desc:'日本重要的工业城市。',
    story:'大阪是日本重要的工业城市,二战期间为日军生产了大量武器装备。' },
  hq_japan_kyoto: { name:'京都', type:'hq', hp:20, rarity:'common', nation:'japan',
    desc:'日本的古都,保留了大量文化遗产。',
    story:'京都曾是日本的古都,保留了大量的历史文化遗产,二战期间未被大规模轰炸。' },
  hq_japan_okinawa: { name:'冲绳', type:'hq', hp:20, rarity:'epic', nation:'japan',
    desc:'日本本土的最后一道屏障。',
    story:'冲绳是日本本土的最后一道屏障,1945年美军在此登陆,双方伤亡惨重。' },
  hq_uk_london: { name:'伦敦', type:'hq', hp:20, rarity:'epic', nation:'uk',
    desc:'大英帝国的首都,经受住了德军的持续轰炸。',
    story:'伦敦是英国的首都,二战期间经受了德军的持续轰炸,但英国人民始终没有屈服。' },
  hq_uk_malta: { name:'马耳他', type:'hq', hp:20, rarity:'rare', nation:'uk',
    desc:'地中海上的战略要地。',
    story:'马耳他是地中海上的战略要地,二战期间在轴心国的猛烈轰炸下坚持抵抗,被誉为“地中海的不沉航母”。' },
  hq_uk_scapa: { name:'斯卡帕湾', type:'hq', hp:20, rarity:'rare', nation:'uk',
    desc:'英国皇家海军的主要基地。',
    story:'斯卡帕湾是英国皇家海军的主要基地,二战期间是英国本土舰队的母港。' },
  hq_uk_alexandria: { name:'亚历山大港', type:'hq', hp:20, rarity:'common', nation:'uk',
    desc:'英国地中海舰队的主要基地。',
    story:'亚历山大港是英国地中海舰队的主要基地,在北非战役中发挥了重要作用。' },
  hq_uk_singapore: { name:'新加坡', type:'hq', hp:20, rarity:'rare', nation:'uk',
    desc:'英国在远东最重要的军事基地。',
    story:'新加坡是英国在远东最重要的军事基地,1942年被日军攻占,是英国历史上最大的军事投降之一。' },
  hq_ussr_moscow: { name:'莫斯科', type:'hq', hp:20, rarity:'epic', nation:'ussr',
    desc:'苏联的首都,1941年粉碎了德军的进攻。',
    story:'莫斯科是苏联的首都,1941年冬苏军在此发动反攻,将德军击退数百公里,打破了德军不可战胜的神话。' },
  hq_ussr_leninrad: { name:'列宁格勒', type:'hq', hp:20, rarity:'epic', nation:'ussr',
    desc:'苏联第二大城市,围城长达872天。',
    story:'列宁格勒是苏联第二大城市,二战期间被德军围困长达872天,居民在极端困难的条件下坚持抵抗。' },
  hq_ussr_stalingrad: { name:'斯大林格勒', type:'hq', hp:20, rarity:'legendary', nation:'ussr',
    desc:'二战的转折点,苏军在此围歼德军第6集团军。',
    story:'斯大林格勒战役是二战的转折点,苏军发动“天王星”行动,合围并歼灭了德军第6集团军。' },
  hq_ussr_kursk: { name:'库尔斯克', type:'hq', hp:20, rarity:'epic', nation:'ussr',
    desc:'史上最大规模坦克战役的发生地。',
    story:'库尔斯克会战是史上规模最大的坦克战役,德军最终未能突破苏军防线,从此在东线彻底丧失战略主动权。' },
  hq_ussr_kiev: { name:'基辅', type:'hq', hp:20, rarity:'rare', nation:'ussr',
    desc:'乌克兰的首府,1941年曾被德军合围。',
    story:'基辅是乌克兰的首府,1941年被德军合围,苏军损失惨重,1943年苏军重新收复该城。' }
};

const CARD_POOL = Object.keys(CARD_DB);
const CARDS_BY_RARITY = {}, CARDS_BY_NATION = {};
Object.entries(CARD_DB).forEach(([id, def]) => {
  (CARDS_BY_RARITY[def.rarity] ||= []).push(id);
  (CARDS_BY_NATION[def.nation] ||= []).push(id);
});

const START_HP = 20, HAND_LIMIT = 6, MAX_KREDITS = 12, DECK_SIZE = 18, DECK_LIMIT = 40, DECK_SLOTS = 5;
const MAIN_CAP_WITH_ALLY = 30, ALLY_CAP = 10;
const $ = id => document.getElementById(id);
const sleep = ms => new Promise(r => setTimeout(r, ms));
const randId = () => Math.random().toString(36).slice(2, 9);

function isRangedUnit(cardId) { const def = CARD_DB[cardId]; return !!(def && def.unitType === 'ranged'); }
function getActionCost(cardOrId) { const def = typeof cardOrId === 'string' ? CARD_DB[cardOrId] : cardOrId; if (!def || def.type !== 'unit') return 0; return Math.max(1, Math.floor(def.atk / 2)); }
function costText(cardOrId) { const def = typeof cardOrId === 'string' ? CARD_DB[cardOrId] : cardOrId; if (!def) return '?'; if (def.type === 'unit') return def.cost + '/' + getActionCost(def); return String(def.cost); }

const DIFFICULTIES = {
  easy:   { id:'easy',   name:'简单', reward:50,  enemyHp:20, aggression:0.40, smart:false, desc:'敌方出牌随意 · 攻击欲望低' },
  normal: { id:'normal', name:'普通', reward:100, enemyHp:20, aggression:0.65, smart:false, desc:'敌方出牌正常 · 攻击欲望中等' },
  hard:   { id:'hard',   name:'困难', reward:200, enemyHp:20, aggression:0.90, smart:true,  desc:'敌方出牌聪明 · 攻击欲望极强' }
};
const DIFF_ORDER = ['easy', 'normal', 'hard'];

const PACKS = {
  normal: {
    name:'普通包', price:100, count:5, cls:'',
    desc:'5 张随机卡牌 · 保底 1 张稀有',
    odds: [
      { common:0.65, rare:0.28, epic:0.06, legendary:0.01 },
      { common:0.65, rare:0.28, epic:0.06, legendary:0.01 },
      { common:0.65, rare:0.28, epic:0.06, legendary:0.01 },
      { common:0.65, rare:0.28, epic:0.06, legendary:0.01 },
      { common:0.00, rare:0.85, epic:0.13, legendary:0.02 }
    ]
  },
  officer: {
    name:'军官包', price:300, count:7, cls:'officer',
    desc:'7 张高品质卡牌 · 保底 1 张特殊或精锐',
    odds: [
      { common:0.40, rare:0.42, epic:0.15, legendary:0.03 },
      { common:0.40, rare:0.42, epic:0.15, legendary:0.03 },
      { common:0.40, rare:0.42, epic:0.15, legendary:0.03 },
      { common:0.40, rare:0.42, epic:0.15, legendary:0.03 },
      { common:0.40, rare:0.42, epic:0.15, legendary:0.03 },
      { common:0.15, rare:0.55, epic:0.25, legendary:0.05 },
      { common:0.00, rare:0.00, epic:0.78, legendary:0.22 }
    ]
  },
  hq: {
    name:'总部盲盒', price:500, count:1, cls:'hq', type:'hq',
    desc:'随机获取 1 张总部牌'
  }
};
function rollRarity(odds) { const r = Math.random(); let acc = 0; for (const key of RARITY_ORDER) { acc += odds[key] || 0; if (r < acc) return key; } return 'common'; }
function pickCardByRarity(rarity) { const pool = CARDS_BY_RARITY[rarity] && CARDS_BY_RARITY[rarity].length ? CARDS_BY_RARITY[rarity] : CARDS_BY_RARITY.common; return pool[Math.floor(Math.random() * pool.length)]; }

function makeEmptyDeck(i) { return { name: `卡组 ${i + 1}`, mainNation: null, allyNation: null, hq: null, cards: [] }; }

let meta = {
  coins: 1000,
  openedPacks: 0,
  ownedCards: {},
  ownedHQs: {},
  packs: { normal: 0, officer: 0 },
  decks: Array.from({ length: DECK_SLOTS }, (_, i) => makeEmptyDeck(i)),
  activeDeckIdx: 0
};

(function initOwnedCards() {
  const perNation = {
    usa: ['usa_1st_infantry','usa_rangers','usa_17th_infantry','usa_sherman','usa_m7_priest','usa_c47_skytrain','usa_blue_devils','usa_naval_support','usa_101st_airborne','usa_82nd_airborne','usa_production_order','usa_war_bonds'],
    ussr: ['ussr_penal_battalion','ussr_partisans','ussr_sniper','ussr_naval_infantry','ussr_ys2_122','ussr_guards_rifles','ussr_kv1','ussr_t34_85','ussr_orden','ussr_moscow_defense'],
    japan: ['japan_ha_go','japan_type97','japan_battleship_yamato','japan_yongsan','japan_imperial_navy','japan_convoy','japan_bataan','japan_imperial_guard','japan_midway','japan_bushido'],
    uk: ['uk_matilda','uk_hurricane','uk_raf','uk_home_guard','uk_convoy','uk_commandos','uk_desert_rats','uk_intelligence','uk_radar','uk_arsenal'],
    germany: ['germany_panzer_iv','germany_bf109','germany_panzer_iii','germany_wehrmacht','germany_volkssturm','germany_stuka','germany_fallschirmjager','germany_stug_iii','germany_u_boat','germany_blitzkrieg']
  };
  Object.values(perNation).flat().forEach(id => { meta.ownedCards[id] = 2; });
})();

(function initOwnedHQs() {
  const defaults = ['hq_germany_berlin','hq_usa_dc','hq_japan_tokyo','hq_uk_london','hq_ussr_moscow'];
  defaults.forEach(id => { meta.ownedHQs[id] = 1; });
})();

function migrateDeck(d, i) {
  if (!d || typeof d !== 'object') return makeEmptyDeck(i);
  return {
    name: String(d.name || `卡组 ${i + 1}`).slice(0, 12),
    mainNation: d.mainNation || null,
    allyNation: d.allyNation || null,
    hq: d.hq || null,
    cards: Array.isArray(d.cards) ? d.cards.slice() : []
  };
}

function migrateMeta(m) {
  const out = Object.assign({
    coins: 0, openedPacks: 0, ownedCards: {}, ownedHQs: {}, packs: { normal: 0, officer: 0 },
    decks: Array.from({ length: DECK_SLOTS }, (_, i) => makeEmptyDeck(i)),
    activeDeckIdx: 0
  }, m || {});
  if (!out.ownedCards) out.ownedCards = {};
  if (!out.ownedHQs || typeof out.ownedHQs !== 'object') out.ownedHQs = {};
  if (!out.packs || typeof out.packs !== 'object') out.packs = { normal: 0, officer: 0 };
  out.packs.normal = Number(out.packs.normal) || 0;
  out.packs.officer = Number(out.packs.officer) || 0;
  if (Array.isArray(m && m.deck)) {
    if (!Array.isArray(out.decks) || out.decks.length === 0) {
      out.decks = Array.from({ length: DECK_SLOTS }, (_, i) => makeEmptyDeck(i));
    }
    out.decks[0] = { name: '默认卡组', mainNation: null, allyNation: null, hq: null, cards: m.deck.slice() };
    delete out.deck;
  }
  const old = Array.isArray(out.decks) ? out.decks : [];
  out.decks = [];
  for (let i = 0; i < DECK_SLOTS; i++) out.decks.push(migrateDeck(old[i], i));
  if (typeof out.activeDeckIdx !== 'number' || out.activeDeckIdx < 0 || out.activeDeckIdx >= DECK_SLOTS) {
    out.activeDeckIdx = 0;
  }
  return out;
}

function updateCoinDisplays() {
  ['lobbyCoins', 'gameCoins', 'shopCoins'].forEach(id => { const el = $(id); if (el) el.textContent = meta.coins; });
}

function getMainCap(deck) { return (deck && deck.allyNation) ? MAIN_CAP_WITH_ALLY : DECK_LIMIT; }
function getAllyCap(deck) { return (deck && deck.allyNation) ? ALLY_CAP : 0; }

function deckMainCount(deck) { if (!deck || !deck.mainNation) return 0; return deck.cards.filter(id => CARD_DB[id] && CARD_DB[id].nation === deck.mainNation).length; }
function deckAllyCount(deck) { if (!deck || !deck.allyNation) return 0; return deck.cards.filter(id => CARD_DB[id] && CARD_DB[id].nation === deck.allyNation).length; }
function deckIsReady(deck) {
  if (!deck || !deck.mainNation || !deck.hq) return false;
  if (!Array.isArray(deck.cards) || deck.cards.length < DECK_LIMIT) return false;
  return true;
}

function generateDefaultDeck(mainNation, allyNation) {
  if (!mainNation) return [];
  const mainList = [], allyList = [];
  Object.keys(CARD_DB).forEach(id => {
    const def = CARD_DB[id];
    if (def.type === 'hq') return;
    if (def.nation === mainNation) mainList.push(id);
    else if (allyNation && def.nation === allyNation) allyList.push(id);
  });
  mainList.sort((a, b) => CARD_DB[a].cost - CARD_DB[b].cost);
  allyList.sort((a, b) => CARD_DB[a].cost - CARD_DB[b].cost);

  const mainCap = allyNation ? MAIN_CAP_WITH_ALLY : DECK_LIMIT;
  const allyCap = allyNation ? ALLY_CAP : 0;
  const deck = [];
  const mainCounts = {};
  for (const id of mainList) { if (deck.length >= mainCap) break; deck.push(id); mainCounts[id] = (mainCounts[id] || 0) + 1; }
  for (const id of mainList) { if (deck.length >= mainCap) break; if ((mainCounts[id] || 0) >= 2) continue; deck.push(id); mainCounts[id] = (mainCounts[id] || 0) + 1; }

  if (allyNation) {
    const allyDeck = [];
    const allyCounts = {};
    for (const id of allyList) { if (allyDeck.length >= allyCap) break; allyDeck.push(id); allyCounts[id] = (allyCounts[id] || 0) + 1; }
    for (const id of allyList) { if (allyDeck.length >= allyCap) break; if ((allyCounts[id] || 0) >= 2) continue; allyDeck.push(id); allyCounts[id] = (allyCounts[id] || 0) + 1; }
    deck.push(...allyDeck);
  }
  return deck;
}

function buildPlayerDeck() {
  const d = meta.decks[meta.activeDeckIdx];
  if (d && Array.isArray(d.cards) && d.cards.length > 0) {
    const copy = d.cards.slice();
    for (let i = copy.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [copy[i], copy[j]] = [copy[j], copy[i]]; }
    return copy;
  }
  return [];
}
function buildEnemyDeck(difficulty) {
  const weights = { easy: { common:0.65, rare:0.25, epic:0.08, legendary:0.02 }, normal: { common:0.45, rare:0.35, epic:0.15, legendary:0.05 }, hard: { common:0.25, rare:0.38, epic:0.25, legendary:0.12 } }[difficulty] || { common:0.45, rare:0.35, epic:0.15, legendary:0.05 };
  const d = [];
  for (let i = 0; i < DECK_SIZE; i++) d.push(pickCardByRarity(rollRarity(weights)));
  return d;
}
function makeSide(owner, hp, deck, kredits) { return { hp, maxHp: hp, kredits: kredits ? 1 : 0, maxKredits: kredits ? 1 : 0, deck, hand: [], counter: null }; }
function newGame(difficulty) {
  const diff = DIFFICULTIES[difficulty] || DIFFICULTIES.normal;
  const playerDeck = buildPlayerDeck();
  if (playerDeck.length === 0) { for (let i = 0; i < DECK_SIZE; i++) playerDeck.push(pickCardByRarity('common')); }
  const st = { turn: 1, active: 'player', over: null, difficulty: diff.id,
    player: makeSide('player', START_HP, playerDeck, false),
    enemy:  makeSide('enemy',  diff.enemyHp, buildEnemyDeck(diff.id), false),
    lanes: { playerHome: [null,null,null,null,null], contested: [null,null,null,null,null], enemyHome: [null,null,null,null,null] } };
  for (let i = 0; i < 4; i++) { drawCard(st, 'player'); drawCard(st, 'enemy'); }
  beginTurn(st, 'player');
  return st;
}
function drawCard(st, side) { const s = st[side]; if (!s.deck.length || s.hand.length >= HAND_LIMIT) return; s.hand.push(s.deck.pop()); }
function beginTurn(st, side) {
  const s = st[side];
  s.maxKredits = Math.min(s.maxKredits + 1, MAX_KREDITS);
  s.kredits = s.maxKredits;
  ['playerHome', 'contested', 'enemyHome'].forEach(laneName => { st.lanes[laneName].forEach(u => { if (u && u.owner === side) { u.ready = true; u.attacksMade = 0; u.hasMoved = false; } }); });
  drawCard(st, side);
}

let gameState = null;
let selectedCard = null;
let selectedUnit = null;

/* ==================== 单位构造 / 词条判定 / 反击结算 ==================== */
function makeUnit(cardId, owner, deployedTurn) {
  const def = CARD_DB[cardId];
  return {
    uid: randId(), id: cardId, owner,
    atk: def.atk, hp: def.hp, maxHp: def.hp,
    ready: hasKeyword(cardId, 'rush'),
    attacksMade: 0, hasMoved: false,
    deployedTurn: deployedTurn || 1
  };
}
function canUnitAttack(unit) {
  if (!unit || !unit.ready) return false;
  return (unit.attacksMade || 0) < getMaxAttacks(unit.id);
}
function isUnitStealthed(unit) {
  if (!unit || !hasKeyword(unit.id, 'stealth')) return false;
  if (!gameState || unit.deployedTurn !== gameState.turn) return false;
  return (unit.attacksMade || 0) === 0 && !unit.hasMoved;
}
function isGuardedFrom(unit, attackerId) {
  const aDef = CARD_DB[attackerId];
  if (!aDef || aDef.unitType !== 'land') return false;
  const loc = findUnitSlot(unit.uid);
  if (!loc) return false;
  const lane = gameState.lanes[loc.laneName];
  for (const adj of [loc.idx - 1, loc.idx + 1]) {
    if (adj < 0 || adj >= lane.length) continue;
    const nb = lane[adj];
    if (nb && nb.owner === unit.owner && nb.uid !== unit.uid && hasKeyword(nb.id, 'guard')) return true;
  }
  return false;
}
function canBeUnitTargeted(target, attackerId) {
  if (isUnitStealthed(target)) return false;
  if (isGuardedFrom(target, attackerId)) return false;
  return true;
}
/* 攻击结算:远程攻击者不遭受反击;首次攻击 + 奇袭不遭受反击;目标被击毁则不反击 */
function resolveAttack(attacker, defender) {
  const aDef = CARD_DB[attacker.id];
  const dAtk = defender.atk;
  defender.hp -= attacker.atk;
  const defenderDied = defender.hp <= 0;
  if (defenderDied) removeUnit(defender.uid);
  let counter = false;
  if (!defenderDied && aDef.unitType !== 'ranged') {
    counter = true;
    if (hasKeyword(attacker.id, 'firststrike') && (attacker.attacksMade || 0) === 0) counter = false;
  }
  if (counter) {
    attacker.hp -= dAtk;
    if (attacker.hp <= 0) removeUnit(attacker.uid);
  }
  consumeAttack(attacker);
}
function consumeAttack(unit) {
  unit.attacksMade = (unit.attacksMade || 0) + 1;
  if (unit.attacksMade >= getMaxAttacks(unit.id) && !hasKeyword(unit.id, 'mobile')) unit.ready = false;
}

function showCardDetail(cardId) {
  const def = CARD_DB[cardId];
  if (!def) return;
  const r = RARITY[def.rarity] || RARITY.common;

  const preview = $('cdPreview');
  preview.innerHTML = '';
  const card = document.createElement('div');
  if (def.type === 'hq') {
    card.className = 'card hq';
    card.innerHTML = cardInnerHq(def);
  } else {
    card.className = 'card ' + cardClassExtras(def) + rarityCls(def);
    card.innerHTML = cardInner(def);
  }
  preview.appendChild(card);

  $('cdName').textContent = def.name;
  const nationEl = $('cdNation');
  if (def.nation && NATIONS[def.nation]) { nationEl.style.display = ''; nationEl.textContent = NATIONS[def.nation].name; }
  else nationEl.style.display = 'none';

  const rarityEl = $('cdRarity');
  rarityEl.textContent = r.name;
  rarityEl.className = 'cd-rarity ' + r.cls;

  if (def.type === 'hq') {
    $('cdCostBadge').textContent = '总部';
    $('cdUType').style.display = 'none';
    $('cdAtk').textContent = '—';
    $('cdHp').textContent = def.hp;
  } else {
    const typeName = def.type === 'command' ? '作战令' : def.type === 'counter' ? '应变' : '单位';
    $('cdCostBadge').textContent = `费用 ${def.cost}${def.type === 'unit' ? ' · 行动 ' + getActionCost(cardId) : ''} · ${typeName}`;
    const utypeEl = $('cdUType');
    if (def.type === 'unit' && def.unitType === 'ranged') { utypeEl.style.display = ''; utypeEl.textContent = '远程'; }
    else if (def.type === 'unit') { utypeEl.style.display = ''; utypeEl.textContent = '陆军'; }
    else utypeEl.style.display = 'none';
    if (def.type === 'unit') { $('cdAtk').textContent = def.atk; $('cdHp').textContent = def.hp; }
    else { $('cdAtk').textContent = '—'; $('cdHp').textContent = '—'; }
  }
  $('cdDesc').textContent = def.desc || '(暂无描述)';

  const kwEl = $('cdKeywords');
  const kws = getKeywords(cardId);
  if (kws.length) {
    let html = '';
    for (const k of kws) {
      const kw = KEYWORDS[k];
      if (!kw) continue;
      html += `<div class="cd-kw-item"><b>${kw.name}</b>${kw.desc}</div>`;
    }
    kwEl.innerHTML = html;
    kwEl.style.display = html ? '' : 'none';
  } else {
    kwEl.innerHTML = '';
    kwEl.style.display = 'none';
  }

  const storyEl = $('cdStory');
  storyEl.style.display = 'none';
  storyEl.textContent = def.story || '暂无历史背景资料。';
  $('cdStoryBtn').textContent = '查看详情';
  $('cardDetailModal').classList.add('show');
}
$('closeCardDetail').onclick = () => $('cardDetailModal').classList.remove('show');
$('cardDetailModal').onclick = e => { if (e.target === $('cardDetailModal')) $('cardDetailModal').classList.remove('show'); };
$('cdStoryBtn').onclick = () => {
  const storyEl = $('cdStory');
  if (storyEl.style.display === 'none') { storyEl.style.display = ''; $('cdStoryBtn').textContent = '收起详情'; }
  else { storyEl.style.display = 'none'; $('cdStoryBtn').textContent = '查看详情'; }
};

function bindCardInteractions(el, { single, dbl }) {
  const LONG_PRESS_MS = 500, MOVE_THRESHOLD = 10;
  let longTimer = null, longFired = false, downPt = null;
  function cancelLong() { if (longTimer) { clearTimeout(longTimer); longTimer = null; } }
  el.addEventListener('contextmenu', e => e.preventDefault());
  el.addEventListener('pointerdown', e => {
    if (e.pointerType === 'mouse' && e.button !== 0) return;
    longFired = false;
    downPt = { x: e.clientX, y: e.clientY };
    cancelLong();
    longTimer = setTimeout(() => { longTimer = null; longFired = true; downPt = null; if (dbl) dbl(); }, LONG_PRESS_MS);
  });
  el.addEventListener('pointermove', e => {
    if (!downPt) return;
    const dx = e.clientX - downPt.x, dy = e.clientY - downPt.y;
    if (dx * dx + dy * dy > MOVE_THRESHOLD * MOVE_THRESHOLD) { cancelLong(); downPt = null; }
  });
  el.addEventListener('pointerup', e => {
    cancelLong();
    if (longFired) { longFired = false; downPt = null; return; }
    if (!downPt) return;
    downPt = null;
    if (single) single();
  });
  el.addEventListener('pointercancel', () => { cancelLong(); longFired = false; downPt = null; });
}

function findUnit(uid) { for (const laneName of ['playerHome', 'contested', 'enemyHome']) { for (const u of gameState.lanes[laneName]) if (u && u.uid === uid) return u; } return null; }
function findUnitSlot(uid) { for (const laneName of ['playerHome', 'contested', 'enemyHome']) { const lane = gameState.lanes[laneName]; for (let i = 0; i < lane.length; i++) if (lane[i] && lane[i].uid === uid) return { laneName, idx: i }; } return null; }
function removeUnit(uid) { const loc = findUnitSlot(uid); if (loc) gameState.lanes[loc.laneName][loc.idx] = null; }
function cardClassExtras(def) { if (def.type === 'command') return 'command '; if (def.type === 'counter') return 'counter '; return ''; }
function cardInner(def) {
  const isUnit = def.type === 'unit';
  const nationAbbr = def.nation && NATIONS[def.nation] ? NATIONS[def.nation].abbr : '';
  const kwRow = keywordBadgesHTML(Object.keys(CARD_DB).find(k => CARD_DB[k] === def) || '');
  return `<span class="cost-badge">${costText(def)}</span>${nationAbbr ? `<span class="nation-badge">${nationAbbr}</span>` : ''}<div class="name">${def.name}</div><div class="kw-row">${kwRow}</div><div class="stats"><span class="atk">${isUnit ? def.atk : '—'}</span><span class="hp">${isUnit ? def.hp : '—'}</span></div>`;
}
function cardInnerHq(def) {
  const nationAbbr = def.nation && NATIONS[def.nation] ? NATIONS[def.nation].abbr : '';
  return `${nationAbbr ? `<span class="nation-badge">${nationAbbr}</span>` : ''}<div class="name">${def.name}</div><div class="stats"><span class="hp">${def.hp}</span></div>`;
}
function cardInnerUnit(unit) {
  const def = CARD_DB[unit.id];
  const nationAbbr = def.nation && NATIONS[def.nation] ? NATIONS[def.nation].abbr : '';
  return `<span class="cost-badge">${costText(def)}</span>${nationAbbr ? `<span class="nation-badge">${nationAbbr}</span>` : ''}<div class="name">${def.name}</div><div class="kw-row">${keywordBadgesHTML(unit.id)}</div><div class="stats"><span class="atk">${unit.atk}</span><span class="hp">${unit.hp}</span></div>`;
}
function rarityCls(def) { return RARITY[def.rarity] ? RARITY[def.rarity].cls : 'r-common'; }

let toastTimer;
function toast(msg) { const el = $('toast'); el.textContent = msg; el.classList.add('show'); clearTimeout(toastTimer); toastTimer = setTimeout(() => el.classList.remove('show'), 1400); }
function canAttackFromCurrentPosition(unit) { if (!unit) return false; const loc = findUnitSlot(unit.uid); if (!loc) return false; if (loc.laneName === 'contested') return true; if (loc.laneName === 'playerHome' || loc.laneName === 'enemyHome') return isRangedUnit(unit.id); return false; }

function getContestedOccupants() { const players = [], enemies = []; gameState.lanes.contested.forEach((u, i) => { if (!u) return; if (u.owner === 'player') players.push({ u, i }); else enemies.push({ u, i }); }); return { players, enemies }; }
function canPlayerEnterContested() { return getContestedOccupants().enemies.length === 0; }
function canEnemyEnterContested() { return getContestedOccupants().players.length === 0; }

function isValidMoveTarget(laneName, idx) { if (!selectedUnit) return false; if (laneName !== 'contested') return false; if (gameState.lanes[laneName][idx]) return false; const unit = findUnit(selectedUnit); if (!unit || !unit.ready || unit.owner !== 'player') return false; const loc = findUnitSlot(selectedUnit); if (!loc || loc.laneName !== 'playerHome') return false; if (!canPlayerEnterContested()) return false; return true; }
function isValidSlotTarget(laneName, idx) { if (!selectedCard) return false; const def = CARD_DB[selectedCard.cardId]; if (def.type !== 'unit') return false; if (laneName !== 'playerHome') return false; if (idx === 2) return false; if (gameState.lanes[laneName][idx]) return false; return true; }
function isValidUnitTargetForCommand(unit) { if (!selectedCard) return false; const def = CARD_DB[selectedCard.cardId]; if (def.type !== 'command') return false; if (def.target === 'enemy_unit' || def.target === 'enemy_unit_or_hq') return unit.owner === 'enemy'; if (def.target === 'player_unit') return unit.owner === 'player'; if (def.target === 'any_unit') return true; return false; }
function updateSelectionHighlights() {
  const handCards = $('playerHand').querySelectorAll('.card');
  handCards.forEach((el, i) => { el.classList.toggle('selected', selectedCard !== null && selectedCard.handIndex === i); });
  document.querySelectorAll('.slot').forEach(el => { const laneName = el.dataset.lane, idx = parseInt(el.dataset.idx); el.classList.toggle('valid-target', isValidSlotTarget(laneName, idx)); el.classList.toggle('valid-move', isValidMoveTarget(laneName, idx)); });
  document.querySelectorAll('.slot .card').forEach(cardEl => {
    const uid = cardEl.dataset.uid;
    if (!uid) return;
    const unit = findUnit(uid);
    if (!unit) return;
    let targetable = false;
    if (selectedCard) targetable = isValidUnitTargetForCommand(unit);
    else if (selectedUnit && unit.owner === 'enemy') {
      const attacker = findUnit(selectedUnit);
      if (attacker && canUnitAttack(attacker) && canAttackFromCurrentPosition(attacker) && canBeUnitTargeted(unit, attacker.id)) targetable = true;
    }
    cardEl.classList.toggle('targetable', targetable);
    cardEl.classList.toggle('selected', uid === selectedUnit);
  });
}

function render() { if (!gameState) return; renderHand('enemy'); renderHand('player'); renderLane('enemyHome'); renderLane('contested'); renderLane('playerHome'); renderHQ(); renderInfo(); updateSelectionHighlights(); }
function renderHand(side) { const handEl = $(side + 'Hand'); handEl.innerHTML = ''; gameState[side].hand.forEach((cardId, i) => { handEl.appendChild(side === 'player' ? makeHandCard(cardId, i) : makeCardBack()); }); }
function renderLane(laneName) {
  const lane = gameState.lanes[laneName];
  const slots = document.querySelectorAll(`.slot[data-lane="${laneName}"]`);
  slots.forEach(slotEl => {
    const idx = parseInt(slotEl.dataset.idx);
    const unit = lane[idx];
    slotEl.className = 'slot' + (unit ? '' : ' empty');
    slotEl.innerHTML = '';
    if (unit) slotEl.appendChild(makeUnitCard(unit));
  });
}
function renderHQ() {
  $('playerHqHp').textContent = gameState.player.hp;
  $('enemyHqHp').textContent = gameState.enemy.hp;
  const pEl = document.querySelector('.hq-slot[data-hq="player"]');
  const eEl = document.querySelector('.hq-slot[data-hq="enemy"]');
  pEl.classList.remove('valid-target'); eEl.classList.remove('valid-target');
  if (selectedCard) {
    const def = CARD_DB[selectedCard.cardId];
    if (def.type === 'counter') { pEl.classList.add('valid-target'); }
    else if (def.type === 'command') { if (def.target === 'player_hq') pEl.classList.add('valid-target'); else if (def.target === 'enemy_unit_or_hq') eEl.classList.add('valid-target'); }
  } else if (selectedUnit) {
    const attacker = findUnit(selectedUnit);
    if (attacker && canUnitAttack(attacker) && canAttackFromCurrentPosition(attacker)) eEl.classList.add('valid-target');
  }
}
function renderInfo() {
  const p = gameState.player, e = gameState.enemy;
  $('playerInfoHp').textContent = `${p.hp} / ${p.maxHp}`;
  $('playerKredits').textContent = `${p.kredits} / ${p.maxKredits}`;
  $('playerMeta').textContent = `手牌 ${p.hand.length} · 牌库 ${p.deck.length}`;
  $('enemyMeta').textContent = `手牌 ${e.hand.length} · 牌库 ${e.deck.length}`;
  const counterEl = $('playerCounter');
  if (p.counter) { const def = CARD_DB[p.counter.id]; counterEl.style.display = ''; counterEl.textContent = '应变 · ' + (def ? def.name : ''); }
  else counterEl.style.display = 'none';
  const diff = DIFFICULTIES[gameState.difficulty] || DIFFICULTIES.normal;
  const dt = $('diffTag');
  dt.textContent = diff.name; dt.className = 'diff-tag ' + diff.id;
  const t = $('turnInfo');
  if (gameState.over === 'win') t.textContent = '胜  利';
  else if (gameState.over === 'lose') t.textContent = '失  败';
  else t.textContent = `第 ${gameState.turn} 回合 · ${gameState.active === 'player' ? '你的回合' : '对方回合'}`;
  $('endTurnBtn').disabled = gameState.active !== 'player' || !!gameState.over;
}

function makeHandCard(cardId, index) {
  const def = CARD_DB[cardId];
  const afford = gameState.player.kredits >= def.cost;
  const el = document.createElement('div');
  el.className = ['card', 'hand', cardClassExtras(def).trim(), rarityCls(def), afford ? '' : 'unaffordable'].filter(Boolean).join(' ');
  el.innerHTML = cardInner(def);
  bindCardInteractions(el, { single: () => handleHandCardClick(index, cardId), dbl: () => showCardDetail(cardId) });
  return el;
}
function makeUnitCard(unit) {
  const def = CARD_DB[unit.id];
  const el = document.createElement('div');
  el.dataset.uid = unit.uid;
  const ready = unit.ready;
  const isMine = unit.owner === 'player';
  const canAct = isMine && canUnitAttack(unit) && gameState.active === 'player' && !gameState.over;
  el.className = ['card', 'unit', rarityCls(def), ready ? '' : 'exhausted', isMine ? '' : 'owned-enemy', canAct ? 'can-act' : ''].filter(Boolean).join(' ');
  el.innerHTML = cardInnerUnit(unit);
  bindCardInteractions(el, { single: () => handleUnitClick(unit), dbl: () => showCardDetail(unit.id) });
  return el;
}
function makeCardBack() { const el = document.createElement('div'); el.className = 'card back'; el.textContent = '指挥官'; return el; }

function handleHandCardClick(index, cardId) {
  if (!gameState || gameState.over || gameState.active !== 'player') return;
  const def = CARD_DB[cardId];
  if (selectedCard && selectedCard.handIndex === index) { selectedCard = null; updateSelectionHighlights(); renderHQ(); return; }
  if (gameState.player.kredits < def.cost) { toast('费用不足'); playDenySound(); return; }
  if (def.type === 'counter' && gameState.player.counter) { toast('已有应变牌在场'); playDenySound(); return; }
  selectedCard = { cardId, handIndex: index };
  selectedUnit = null;
  updateSelectionHighlights(); renderHQ();
}

function handleUnitClick(unit) {
  if (!gameState || gameState.over) return;
  if (selectedCard) {
    const def = CARD_DB[selectedCard.cardId];
    if (def.type === 'command' && isValidUnitTargetForCommand(unit)) { applyCommandToUnit(def, unit); return; }
  }
  if (unit.owner === 'player') {
    if (gameState.active !== 'player' || !unit.ready) return;
    if (selectedUnit === unit.uid) selectedUnit = null;
    else { selectedUnit = unit.uid; selectedCard = null; }
    updateSelectionHighlights(); renderHQ();
    return;
  }
  if (unit.owner === 'enemy' && selectedUnit) {
    const attacker = findUnit(selectedUnit);
    if (!attacker || !canUnitAttack(attacker)) { selectedUnit = null; render(); return; }
    if (!canAttackFromCurrentPosition(attacker)) { toast('需要移动到交战区才能攻击'); playDenySound(); return; }
    const actionCost = getActionCost(attacker.id);
    if (gameState.player.kredits < actionCost) { toast(`行动费用不足(需要 ${actionCost})`); playDenySound(); return; }
    if (!canBeUnitTargeted(unit, attacker.id)) {
      toast(isUnitStealthed(unit) ? '目标处于隐匿状态' : '目标受到护卫保护');
      playDenySound(); return;
    }
    gameState.player.kredits -= actionCost;
    resolveAttack(attacker, unit);
    selectedUnit = null;
    render();
  }
}

document.querySelectorAll('.slot').forEach(slotEl => {
  slotEl.addEventListener('click', (e) => {
    if (!gameState || gameState.over || gameState.active !== 'player') return;
    if (e.target.closest && e.target.closest('.card')) return;
    const laneName = slotEl.dataset.lane, idx = parseInt(slotEl.dataset.idx);
    const unit = gameState.lanes[laneName][idx];
    if (unit) { handleUnitClick(unit); return; }
    if (selectedUnit && isValidMoveTarget(laneName, idx)) { moveUnit(selectedUnit, laneName, idx); return; }
    if (selectedCard) {
      const def = CARD_DB[selectedCard.cardId];
      if (def.type === 'unit' && isValidSlotTarget(laneName, idx)) { placeUnit(selectedCard.cardId, selectedCard.handIndex, laneName, idx); return; }
    }
    if (selectedCard || selectedUnit) playDenySound();
    selectedCard = null; selectedUnit = null;
    updateSelectionHighlights(); renderHQ();
  });
});

document.querySelectorAll('.hq-slot').forEach(hqEl => {
  hqEl.addEventListener('click', () => {
    if (!gameState || gameState.over || gameState.active !== 'player') return;
    const side = hqEl.dataset.hq;
    if (selectedCard) {
      const def = CARD_DB[selectedCard.cardId];
      if (def.type === 'counter' && side === 'player') { playCounter(); return; }
      if (def.type === 'command' && def.target === 'player_hq' && side === 'player') { applyCommandToHQ(def); return; }
      if (def.type === 'command' && def.target === 'enemy_unit_or_hq' && side === 'enemy') { applyCommandToEnemyHQ(def); return; }
    }
    if (selectedUnit && side === 'enemy') {
      const attacker = findUnit(selectedUnit);
      if (!attacker || !canUnitAttack(attacker)) { selectedUnit = null; render(); return; }
      if (!canAttackFromCurrentPosition(attacker)) { toast('需要移动到交战区才能攻击'); playDenySound(); return; }
      const actionCost = getActionCost(attacker.id);
      if (gameState.player.kredits < actionCost) { toast(`行动费用不足(需要 ${actionCost})`); playDenySound(); return; }
      gameState.player.kredits -= actionCost;
      let dmg = triggerCounter('enemy_attack_hq', { damage: attacker.atk });
      gameState.enemy.hp = Math.max(0, gameState.enemy.hp - dmg);
      consumeAttack(attacker);
      selectedUnit = null;
      render();
      if (gameState.enemy.hp <= 0) finish('win');
      return;
    }
    if (selectedCard || selectedUnit) playDenySound();
    selectedCard = null; selectedUnit = null;
    updateSelectionHighlights(); renderHQ();
  });
});

function placeUnit(cardId, handIndex, laneName, idx) {
  const def = CARD_DB[cardId], p = gameState.player;
  if (p.kredits < def.cost) { toast('费用不足'); return; }
  if (gameState.lanes[laneName][idx]) return;
  if (laneName !== 'playerHome') return;
  p.kredits -= def.cost;
  p.hand.splice(handIndex, 1);
  gameState.lanes[laneName][idx] = makeUnit(cardId, 'player', gameState.turn);
  selectedCard = null;
  render();
}
function moveUnit(uid, toLaneName, toIdx) {
  const unit = findUnit(uid);
  if (!unit || !unit.ready || unit.owner !== 'player') return;
  const loc = findUnitSlot(uid);
  if (!loc || loc.laneName !== 'playerHome') return;
  if (toLaneName !== 'contested') return;
  if (gameState.lanes[toLaneName][toIdx]) return;
  if (!canPlayerEnterContested()) { toast('交战区被敌方控制'); return; }
  gameState.lanes[toLaneName][toIdx] = unit;
  gameState.lanes[loc.laneName][loc.idx] = null;
  unit.hasMoved = true;
  selectedUnit = null;
  render();
}

function applyCommandToHQ(def) {
  const p = gameState.player;
  if (p.kredits < def.cost) { toast('费用不足'); return; }
  p.kredits -= def.cost;
  p.hand.splice(selectedCard.handIndex, 1);
  const eff = def.effect;
  if (eff.type === 'heal_hq') { p.hp = Math.min(p.maxHp, p.hp + eff.value); toast(`${def.name}:总部恢复 ${eff.value} 点生命`); }
  else if (eff.type === 'buff_all') {
    let count = 0;
    ['playerHome', 'contested'].forEach(laneName => { gameState.lanes[laneName].forEach(u => { if (u && u.owner === 'player') { u.atk += eff.atk || 0; u.hp += eff.hp || 0; u.maxHp += eff.hp || 0; count++; } }); });
    toast(count === 0 ? '场上没有我方单位' : `${def.name}:${count} 个单位获得 +${eff.atk || 0}/+${eff.hp || 0}`);
  }
  selectedCard = null;
  render();
}
function applyCommandToUnit(def, target) {
  const p = gameState.player;
  if (p.kredits < def.cost) { toast('费用不足'); return; }
  p.kredits -= def.cost;
  p.hand.splice(selectedCard.handIndex, 1);
  const eff = def.effect;
  if (eff.type === 'damage') { target.hp -= eff.value; if (target.hp <= 0) removeUnit(target.uid); toast(`${def.name}:造成 ${eff.value} 点伤害`); }
  else if (eff.type === 'buff') { target.atk += eff.atk || 0; target.hp += eff.hp || 0; target.maxHp += eff.hp || 0; toast(`${def.name}:目标获得 +${eff.atk || 0}/+${eff.hp || 0}`); }
  selectedCard = null;
  render();
}
function applyCommandToEnemyHQ(def) {
  const p = gameState.player;
  if (p.kredits < def.cost) { toast('费用不足'); return; }
  p.kredits -= def.cost;
  p.hand.splice(selectedCard.handIndex, 1);
  const eff = def.effect;
  if (eff.type === 'damage') { gameState.enemy.hp = Math.max(0, gameState.enemy.hp - eff.value); toast(`${def.name}:敌方总部受到 ${eff.value} 点伤害`); }
  selectedCard = null;
  render();
  if (gameState.enemy.hp <= 0) finish('win');
}
function playCounter() {
  if (!selectedCard) return;
  const def = CARD_DB[selectedCard.cardId];
  const p = gameState.player;
  if (p.counter) { toast('已有应变牌在场'); return; }
  if (p.kredits < def.cost) { toast('费用不足'); return; }
  p.kredits -= def.cost;
  p.hand.splice(selectedCard.handIndex, 1);
  p.counter = { id: selectedCard.cardId, name: def.name };
  toast(`${def.name} 已设下,等待敌方触发`);
  selectedCard = null;
  render();
}
function triggerCounter(triggerName, ctx) {
  if (!gameState || !gameState.player.counter) return ctx && ctx.damage != null ? ctx.damage : 0;
  const counter = gameState.player.counter;
  const def = CARD_DB[counter.id];
  if (!def || def.type !== 'counter' || def.trigger !== triggerName) return ctx && ctx.damage != null ? ctx.damage : 0;
  const eff = def.effect || {};
  let newDamage = ctx && ctx.damage != null ? ctx.damage : 0;
  if (eff.type === 'damage_unit' && ctx && ctx.unit) { ctx.unit.hp -= eff.value; if (ctx.unit.hp <= 0) removeUnit(ctx.unit.uid); toast(`${def.name} 触发:对目标造成 ${eff.value} 点伤害`); }
  else if (eff.type === 'damage_hq') { gameState.enemy.hp = Math.max(0, gameState.enemy.hp - eff.value); toast(`${def.name} 触发:敌方总部受到 ${eff.value} 点伤害`); }
  else if (eff.type === 'reduce_damage') { newDamage = Math.max(0, newDamage - eff.value); toast(`${def.name} 触发:本次伤害减少 ${eff.value} 点`); }
  gameState.player.counter = null;
  return newDamage;
}

$('endTurnBtn').onclick = endTurn;
function endTurn() {
  if (!gameState || gameState.over || gameState.active !== 'player') return;
  selectedCard = null; selectedUnit = null;
  gameState.active = 'enemy';
  beginTurn(gameState, 'enemy');
  render();
  enemyTurn();
}
async function enemyTurn() {
  await sleep(450);
  if (!gameState || gameState.over) return;
  const e = gameState.enemy;
  const diff = DIFFICULTIES[gameState.difficulty] || DIFFICULTIES.normal;

  while (true) {
    let best = -1, bestCost = -1;
    e.hand.forEach((id, i) => { const def = CARD_DB[id]; if (def.type !== 'unit') return; if (def.cost <= e.kredits && def.cost > bestCost) { best = i; bestCost = def.cost; } });
    if (best === -1) break;
    const target = findEnemySlot();
    if (!target) break;
    const cardId = e.hand[best], def = CARD_DB[cardId];
    e.kredits -= def.cost;
    e.hand.splice(best, 1);
    const newUnit = makeUnit(cardId, 'enemy', gameState.turn);
    gameState.lanes[target.laneName][target.idx] = newUnit;
    if (gameState.player.counter) { triggerCounter('enemy_deploy', { unit: newUnit }); if (gameState.enemy.hp <= 0) { render(); finish('win'); return; } }
    render();
    await sleep(380);
  }

  if (canEnemyEnterContested()) {
    for (const u of gameState.lanes.enemyHome.slice()) {
      if (!u || !u.ready) continue;
      if (isRangedUnit(u.id)) continue;
      const slot = gameState.lanes.contested.findIndex(x => !x);
      if (slot === -1) break;
      const idx = gameState.lanes.enemyHome.indexOf(u);
      if (idx === -1) continue;
      gameState.lanes.contested[slot] = u;
      gameState.lanes.enemyHome[idx] = null;
      u.hasMoved = true;
      render();
      await sleep(280);
    }
  }

  for (const laneName of ['contested', 'enemyHome']) {
    const lane = gameState.lanes[laneName];
    for (const u of lane) {
      if (!u || u.owner !== 'enemy' || !canUnitAttack(u)) continue;
      if (gameState.over) return;
      if (laneName === 'enemyHome' && !isRangedUnit(u.id)) continue;
      const myUnits = [];
      ['playerHome', 'contested'].forEach(ln => { gameState.lanes[ln].forEach(x => { if (x && x.owner === 'player' && canBeUnitTargeted(x, u.id)) myUnits.push(x); }); });

      let attackUnit = false;
      let tgt = null;
      if (myUnits.length) {
        if (diff.smart) {
          const killable = myUnits.filter(x => x.hp <= u.atk);
          if (killable.length) {
            killable.sort((a, b) => (b.atk * 2 + b.hp) - (a.atk * 2 + a.hp));
            tgt = killable[0];
            attackUnit = true;
          } else if (Math.random() < diff.aggression) {
            const sorted = myUnits.slice().sort((a, b) => (b.atk * 2 + b.hp) - (a.atk * 2 + a.hp));
            tgt = sorted[0];
            attackUnit = true;
          }
        } else if (Math.random() < diff.aggression) {
          tgt = myUnits[Math.floor(Math.random() * myUnits.length)];
          attackUnit = true;
        }
      }

      if (attackUnit && tgt) {
        resolveAttack(u, tgt);
      } else {
        let dmg = u.atk;
        dmg = triggerCounter('enemy_attack_hq', { damage: dmg });
        gameState.player.hp = Math.max(0, gameState.player.hp - dmg);
        consumeAttack(u);
      }
      render();
      await sleep(320);
      if (gameState.player.hp <= 0) { finish('lose'); return; }
    }
  }

  gameState.active = 'player';
  gameState.turn++;
  beginTurn(gameState, 'player');
  render();
}
function findEnemySlot() { for (const i of [1, 3, 0, 4]) { if (!gameState.lanes.enemyHome[i]) return { laneName: 'enemyHome', idx: i }; } return null; }

function finish(result) {
  gameState.over = result;
  selectedCard = null; selectedUnit = null;
  const diff = DIFFICULTIES[gameState.difficulty] || DIFFICULTIES.normal;
  const reward = result === 'win' ? diff.reward : Math.floor(diff.reward * 0.3);
  meta.coins += reward;
  playCoinSound();
  updateCoinDisplays();
  render();
  $('overlayTitle').textContent = result === 'win' ? '胜  利' : '失  败';
  $('overlayTitle').className = 'overlay-title ' + (result === 'win' ? 'win' : 'lose');
  $('overlayReward').textContent = `+${reward} 金币`;
  $('overlay').classList.add('show');
}

const lobby = $('lobby');
function showLobby() {
  ['overlay', 'modal', 'shopModal', 'settingsModal', 'cardDetailModal', 'packOverlay', 'codexModal', 'battleModal', 'creditsModal', 'packModal', 'versionModal'].forEach(id => { const el = $(id); if (el) el.classList.remove('show'); });
  lobby.classList.remove('hidden');
  updateCoinDisplays();
  startHallMusic();
}
function enterGame() { lobby.classList.add('hidden'); $('overlay').classList.remove('show'); stopHallMusic(); }
$('loadBtn').onclick = () => { $('saveCode').value = ''; $('modal').classList.add('show'); };
$('settingsBtn').onclick = () => {
  document.querySelectorAll('#settingsModal .settings-label').forEach(el => el.style.display = '');
  $('hallVolume').style.display = '';
  $('settingsModal').classList.add('show');
};
$('gameSettingsBtn').onclick = () => {
  document.querySelectorAll('#settingsModal .settings-label').forEach(el => el.style.display = 'none');
  $('hallVolume').style.display = 'none';
  $('settingsModal').classList.add('show');
};
$('closeSettings').onclick = () => $('settingsModal').classList.remove('show');
$('settingsModal').onclick = e => { if (e.target === $('settingsModal')) $('settingsModal').classList.remove('show'); };
$('creditsBtn').onclick = () => { $('settingsModal').classList.remove('show'); $('creditsModal').classList.add('show'); };
$('closeCredits').onclick = () => $('creditsModal').classList.remove('show');
$('creditsModal').onclick = e => { if (e.target === $('creditsModal')) $('creditsModal').classList.remove('show'); };

function renderVersionList() {
  const list = $('versionList');
  list.innerHTML = '';
  VERSIONS.forEach(v => {
    const item = document.createElement('div');
    item.className = 'version-item';
    const head = document.createElement('div');
    head.className = 'v-head';
    head.innerHTML = `<span class="v-num">${v.version}</span><span class="v-title">${v.title}</span><span class="v-date">${v.date}</span>`;
    item.appendChild(head);
    const ul = document.createElement('ul');
    v.items.forEach(t => { const li = document.createElement('li'); li.textContent = t; ul.appendChild(li); });
    item.appendChild(ul);
    list.appendChild(item);
  });
}
$('versionBtn').onclick = () => { renderVersionList(); $('versionModal').classList.add('show'); };
$('closeVersion').onclick = () => $('versionModal').classList.remove('show');
$('versionModal').onclick = e => { if (e.target === $('versionModal')) $('versionModal').classList.remove('show'); };

$('settingsHomeBtn').onclick = () => {
  if (gameState && gameState.active !== 'player') { toast('请等待对方回合结束'); playDenySound(); return; }
  $('settingsModal').classList.remove('show');
  showLobby();
};
$('settingsSaveBtn').onclick = () => { $('settingsModal').classList.remove('show'); $('modal').classList.add('show'); };

const hallVolumeSlider = $('hallVolume');
if (hallVolumeSlider) {
  hallVolumeSlider.value = hallVolume;
  hallVolumeSlider.addEventListener('input', e => { setHallVolume(parseFloat(e.target.value)); });
}

document.addEventListener('pointerdown', () => { if(!lobby.classList.contains('hidden')) startHallMusic(); }, true);
document.addEventListener('keydown', () => { if(!lobby.classList.contains('hidden')) startHallMusic(); }, true);

let pickedDifficulty = 'normal';
let pickedDeckIdx = 0;
function openBattleModal() { pickedDifficulty = 'normal'; pickedDeckIdx = meta.activeDeckIdx || 0; renderBattleModal(); $('battleModal').classList.add('show'); }
$('startBtn').onclick = openBattleModal;
$('closeBattle').onclick = () => $('battleModal').classList.remove('show');
$('battleModal').onclick = e => { if (e.target === $('battleModal')) $('battleModal').classList.remove('show'); };

function renderBattleModal() {
  const diffList = $('diffList');
  diffList.innerHTML = '';
  DIFF_ORDER.forEach(id => {
    const d = DIFFICULTIES[id];
    const btn = document.createElement('button');
    btn.className = 'diff-btn' + (pickedDifficulty === id ? ' selected' : '');
    btn.innerHTML = `<div style="flex:1 1 auto"><div class="d-name">${d.name}</div><div class="d-desc">${d.desc}</div></div><div class="d-reward">+${d.reward}</div>`;
    btn.onclick = () => { pickedDifficulty = id; renderBattleModal(); };
    diffList.appendChild(btn);
  });
  const deckList = $('deckPickList');
  deckList.innerHTML = '';
  let anyReady = false;
  meta.decks.forEach((deck, i) => {
    const cards = Array.isArray(deck.cards) ? deck.cards : [];
    const hasNation = deck.mainNation && deck.hq;
    const ready = deckIsReady(deck);
    if (ready) anyReady = true;
    const btn = document.createElement('button');
    btn.className = 'deck-pick' + (pickedDeckIdx === i ? ' selected' : '') + (!ready ? ' incomplete' : '');
    btn.disabled = !ready;
    const status = !hasNation ? '未选国家/总部' : (cards.length + '/40' + (ready ? '' : ' 牌数不足'));
    btn.innerHTML = `<div class="dp-name">${deck.name || `卡组 ${i + 1}`}</div><div class="dp-count">${status}</div>`;
    if (ready) btn.onclick = () => { pickedDeckIdx = i; renderBattleModal(); };
    deckList.appendChild(btn);
  });
  if (!anyReady) {
    const note = document.createElement('div');
    note.style.cssText = 'font-size:11px;color:var(--dim);text-align:center;padding:6px;line-height:1.6';
    note.textContent = '暂无可用卡组。请到「卡牌图鉴」选择主国与总部(盟国可选),并凑满 40 张卡牌。';
    deckList.appendChild(note);
  }
  const selDeck = meta.decks[pickedDeckIdx];
  const selOk = deckIsReady(selDeck);
  $('battleStartBtn').disabled = !selOk;
  $('battleStartBtn').textContent = selOk ? '开 始 战 役' : '请先组建完整卡组';
}
$('battleStartBtn').onclick = () => {
  const selDeck = meta.decks[pickedDeckIdx];
  if (!deckIsReady(selDeck)) { toast('卡组未完成,请先凑满 40 张'); playDenySound(); return; }
  meta.activeDeckIdx = pickedDeckIdx;
  gameState = newGame(pickedDifficulty);
  selectedCard = null; selectedUnit = null;
  $('battleModal').classList.remove('show');
  enterGame();
  render();
};

/* ==================== 商店 ==================== */
$('shopBtn').onclick = () => { renderShop(); updateCoinDisplays(); $('shopModal').classList.add('show'); };
$('closeShop').onclick = () => $('shopModal').classList.remove('show');
$('shopModal').onclick = e => { if (e.target === $('shopModal')) $('shopModal').classList.remove('show'); };

function renderShop() {
  const list = $('shopList');
  list.innerHTML = '';
  Object.entries(PACKS).forEach(([id, pack]) => {
    const afford = meta.coins >= pack.price;
    const isHq = pack.type === 'hq';
    const ownedLine = isHq ? '' : `<div class="shop-pack-owned">已有 ${meta.packs[id] || 0} 个</div>`;
    const el = document.createElement('div');
    el.className = 'shop-pack ' + (pack.cls || '');
    el.innerHTML = `
      <div class="shop-pack-body">
        <div class="shop-pack-name">${pack.name}</div>
        <div class="shop-pack-desc">${pack.desc}</div>
        ${ownedLine}
      </div>
      <button class="shop-buy" data-pack="${id}" ${afford ? '' : 'disabled'}>${pack.price} 金币</button>
    `;
    list.appendChild(el);
  });
  list.querySelectorAll('.shop-buy').forEach(btn => { btn.onclick = () => buyPack(btn.dataset.pack); });
  renderHqOwned();
}

function renderHqOwned() {
  const cont = $('hqOwnedList');
  if (!cont) return;
  cont.innerHTML = '';
  const owned = Object.keys(meta.ownedHQs || {}).filter(id => meta.ownedHQs[id] > 0 && CARD_DB[id]);
  if (owned.length === 0) {
    cont.innerHTML = '<div class="hq-empty-note">还没有总部牌<br>去购买总部盲盒试试</div>';
    return;
  }
  owned.sort((a, b) => {
    const na = NATION_ORDER.indexOf(CARD_DB[a].nation);
    const nb = NATION_ORDER.indexOf(CARD_DB[b].nation);
    if (na !== nb) return na - nb;
    return (a < b) ? -1 : (a > b ? 1 : 0);
  });
  owned.forEach(id => {
    const def = CARD_DB[id];
    const el = document.createElement('div');
    el.className = 'card hq';
    el.innerHTML = cardInnerHq(def);
    const badge = document.createElement('span');
    badge.className = 'owned-badge';
    badge.textContent = 'x' + meta.ownedHQs[id];
    el.appendChild(badge);
    bindCardInteractions(el, { single: null, dbl: () => showCardDetail(id) });
    cont.appendChild(el);
  });
}

function buyPack(packId) {
  const pack = PACKS[packId];
  if (!pack) return;
  if (meta.coins < pack.price) { toast('金币不足'); playDenySound(); return; }
  meta.coins -= pack.price;
  playCoinSound();
  updateCoinDisplays();

  if (pack.type === 'hq') {
    const hqIds = Object.keys(CARD_DB).filter(id => CARD_DB[id].type === 'hq');
    const cardId = hqIds[Math.floor(Math.random() * hqIds.length)];
    meta.ownedHQs[cardId] = (meta.ownedHQs[cardId] || 0) + 1;
    renderShop();
    showHqReveal(cardId);
    return;
  }

  meta.packs[packId] = (meta.packs[packId] || 0) + 1;
  renderShop();
  toast(`${pack.name} 已存入拆包`);
}

/* ==================== 拆包 ==================== */
let selectedPackId = 'normal';

$('packBtn').onclick = () => {
  if (meta.packs.normal > 0) selectedPackId = 'normal';
  else if (meta.packs.officer > 0) selectedPackId = 'officer';
  renderPackRoom();
  $('packModal').classList.add('show');
};
$('closePackModal').onclick = () => $('packModal').classList.remove('show');
$('packModal').onclick = e => { if (e.target === $('packModal')) $('packModal').classList.remove('show'); };

function renderPackRoom() {
  const cont = $('packRoomList');
  cont.innerHTML = '';
  let total = 0;
  Object.entries(PACKS).forEach(([id, pack]) => {
    if (pack.type === 'hq') return;
    const count = meta.packs[id] || 0;
    total += count;
    const el = document.createElement('div');
    el.className = 'pack-room-item' + (selectedPackId === id ? ' selected' : '') + (pack.cls ? ' ' + pack.cls : '') + (count === 0 ? ' empty' : '');
    el.innerHTML = `<div class="pack-room-item-name">${pack.name}</div><div class="pack-room-item-count">×${count}</div>`;
    el.onclick = () => { selectedPackId = id; renderPackRoom(); };
    cont.appendChild(el);
  });
  const count = meta.packs[selectedPackId] || 0;
  $('packOpenBtn').disabled = count === 0;
  $('packRoomNote').textContent = total === 0 ? '还没有卡包,去商店购买后再来开启' : '点击开启按钮拆开所选卡包';
}
$('packOpenBtn').onclick = () => {
  const packId = selectedPackId;
  const pack = PACKS[packId];
  if (!pack) return;
  if ((meta.packs[packId] || 0) <= 0) { toast('没有这个卡包'); playDenySound(); return; }
  meta.packs[packId]--;

  playRipSound();

  const cardIds = [];
  for (let i = 0; i < pack.count; i++) {
    const odds = pack.odds[i] || pack.odds[pack.odds.length - 1];
    const rarity = rollRarity(odds);
    const cardId = pickCardByRarity(rarity);
    cardIds.push(cardId);
    meta.ownedCards[cardId] = (meta.ownedCards[cardId] || 0) + 1;
  }
  meta.openedPacks = (meta.openedPacks || 0) + 1;

  renderPackRoom();
  $('packModal').classList.remove('show');
  showPackReveal(pack, cardIds);
};

function showPackReveal(pack, cardIds) {
  $('packTitle').innerHTML = `${pack.name}<small>点击卡牌翻开 · 翻开后再点看详情</small>`;
  const cont = $('packCards');
  cont.innerHTML = '';
  $('packOk').style.display = 'none';
  let revealed = 0;
  const total = cardIds.length;
  cardIds.forEach((cardId, i) => {
    const el = document.createElement('div');
    el.className = 'card back';
    el.textContent = '指挥官';
    el.style.animationDelay = (i * 0.08) + 's';
    let isRevealed = false;
    el.addEventListener('click', () => {
      if (isRevealed) { showCardDetail(cardId); return; }
      isRevealed = true;
      const def = CARD_DB[cardId];
      el.className = 'card ' + cardClassExtras(def) + rarityCls(def);
      el.innerHTML = cardInner(def);
      el.style.animation = 'none';
      void el.offsetWidth;
      el.style.animation = 'flipIn .3s ease';
      revealed++;
      if (revealed === total) $('packOk').style.display = '';
    });
    cont.appendChild(el);
  });
  $('packOverlay').classList.add('show');
}
$('packOk').onclick = () => $('packOverlay').classList.remove('show');

function showHqReveal(cardId) {
  $('packTitle').innerHTML = `总部盲盒<small>点击卡牌翻开 · 翻开后再点看详情</small>`;
  const cont = $('packCards');
  cont.innerHTML = '';
  $('packOk').style.display = 'none';
  const el = document.createElement('div');
  el.className = 'card hq back';
  el.textContent = '总部';
  let isRevealed = false;
  el.addEventListener('click', () => {
    if (isRevealed) { showCardDetail(cardId); return; }
    isRevealed = true;
    const def = CARD_DB[cardId];
    el.className = 'card hq';
    el.innerHTML = cardInnerHq(def);
    el.style.animation = 'none';
    void el.offsetWidth;
    el.style.animation = 'flipIn .3s ease';
    $('packOk').style.display = '';
  });
  cont.appendChild(el);
  $('packOverlay').classList.add('show');
}

/* ==================== 图鉴 + 卡组编辑 ==================== */
let editDeckIdx = 0;
let draftDeck = [];
let draftMainNation = null;
let draftAllyNation = null;
let draftHq = null;
let codexNationFilter = 'main';
let pendingMain = null, pendingAlly = null, pendingHq = null;

function openCodex() {
  editDeckIdx = meta.activeDeckIdx || 0;
  loadDeckIntoDraft(editDeckIdx);
  updateCodexView();
  $('codexModal').classList.add('show');
}
function loadDeckIntoDraft(i) {
  const deck = meta.decks[i];
  draftDeck = deck && Array.isArray(deck.cards) ? deck.cards.slice() : [];
  draftMainNation = (deck && deck.mainNation) || null;
  draftAllyNation = (deck && deck.allyNation) || null;
  draftHq = (deck && deck.hq) || null;
  $('deckNameInput').value = (deck && deck.name) || `卡组 ${i + 1}`;
  codexNationFilter = 'main';
  pendingMain = draftMainNation;
  pendingAlly = draftAllyNation;
  pendingHq = draftHq;
}

function updateCodexView() {
  renderDeckTabs();
  const needsSetup = !draftMainNation || !draftHq;
  if (needsSetup) {
    $('nationSetup').style.display = '';
    $('deckEditor').style.display = 'none';
    renderNationSetup();
  } else {
    $('nationSetup').style.display = 'none';
    $('deckEditor').style.display = '';
    renderCodex();
  }
}

function renderDeckTabs() {
  const tabs = $('deckTabs');
  tabs.innerHTML = '';
  meta.decks.forEach((deck, i) => {
    const cards = Array.isArray(deck.cards) ? deck.cards : [];
    const btn = document.createElement('button');
    btn.className = 'deck-tab' + (i === editDeckIdx ? ' active' : '');
    let natLabel = '未选';
    if (deck.mainNation) {
      natLabel = deck.allyNation
        ? `${NATIONS[deck.mainNation].abbr}+${NATIONS[deck.allyNation].abbr}`
        : NATIONS[deck.mainNation].abbr;
    }
    btn.innerHTML = `${(deck.name || `卡组 ${i + 1}`)} <small>${natLabel} ${cards.length}</small>`;
    btn.onclick = () => switchEditDeck(i);
    tabs.appendChild(btn);
  });
}

function renderNationSetup() {
  if (!pendingMain && draftMainNation) pendingMain = draftMainNation;
  if (!pendingAlly && draftAllyNation) pendingAlly = draftAllyNation;
  if (!pendingHq && draftHq) pendingHq = draftHq;

  const mainRow = $('mainNationRow');
  mainRow.innerHTML = '';
  NATION_ORDER.forEach(nid => {
    const btn = document.createElement('button');
    btn.className = 'nation-setup-btn' + (pendingMain === nid ? ' selected' : '');
    btn.textContent = NATIONS[nid].name;
    btn.onclick = () => {
      pendingMain = nid;
      if (pendingAlly === nid) pendingAlly = null;
      if (pendingHq) {
        const hqDef = CARD_DB[pendingHq];
        if (!hqDef || (hqDef.nation !== pendingMain && hqDef.nation !== pendingAlly)) pendingHq = null;
      }
      renderNationSetup();
    };
    mainRow.appendChild(btn);
  });

  const allyRow = $('allyNationRow');
  allyRow.innerHTML = '';
  const noneBtn = document.createElement('button');
  noneBtn.className = 'nation-setup-btn' + (!pendingAlly ? ' selected' : '');
  noneBtn.textContent = '不选';
  noneBtn.onclick = () => {
    pendingAlly = null;
    if (pendingHq) {
      const hqDef = CARD_DB[pendingHq];
      if (!hqDef || hqDef.nation !== pendingMain) pendingHq = null;
    }
    renderNationSetup();
  };
  allyRow.appendChild(noneBtn);
  NATION_ORDER.forEach(nid => {
    const btn = document.createElement('button');
    btn.className = 'nation-setup-btn' + (pendingAlly === nid ? ' selected' : '');
    btn.textContent = NATIONS[nid].name;
    btn.disabled = pendingMain === nid;
    btn.onclick = () => {
      pendingAlly = nid;
      if (pendingHq) {
        const hqDef = CARD_DB[pendingHq];
        if (!hqDef || (hqDef.nation !== pendingMain && hqDef.nation !== pendingAlly)) pendingHq = null;
      }
      renderNationSetup();
    };
    allyRow.appendChild(btn);
  });

  const hqRow = $('hqRow');
  hqRow.innerHTML = '';
  if (!pendingMain) {
    const note = document.createElement('div');
    note.style.cssText = 'font-size:11px;color:var(--dim);padding:6px';
    note.textContent = '请先选择主国';
    hqRow.appendChild(note);
  } else {
    const availHq = Object.keys(meta.ownedHQs).filter(id => {
      if (!meta.ownedHQs[id] || meta.ownedHQs[id] <= 0) return false;
      const def = CARD_DB[id];
      if (!def || def.type !== 'hq') return false;
      if (def.nation === pendingMain) return true;
      if (pendingAlly && def.nation === pendingAlly) return true;
      return false;
    });
    if (availHq.length === 0) {
      const note = document.createElement('div');
      note.style.cssText = 'font-size:11px;color:var(--red);padding:6px;line-height:1.6';
      note.textContent = '没有可用于该组合的总部。请先到商店购买总部盲盒。';
      hqRow.appendChild(note);
    } else {
      availHq.forEach(hqId => {
        const def = CARD_DB[hqId];
        const btn = document.createElement('button');
        btn.className = 'nation-setup-btn' + (pendingHq === hqId ? ' selected' : '');
        btn.textContent = def.name;
        btn.onclick = () => { pendingHq = hqId; renderNationSetup(); };
        hqRow.appendChild(btn);
      });
    }
  }

  const okReady = !!(pendingMain && pendingHq);
  $('confirmNationsBtn').disabled = !okReady;
  $('useActiveDeckBtn').disabled = !okReady;
}

$('confirmNationsBtn').onclick = () => {
  if (!pendingMain || !pendingHq) return;
  draftMainNation = pendingMain;
  draftAllyNation = pendingAlly;
  draftHq = pendingHq;
  draftDeck = [];
  updateCodexView();
};

$('useActiveDeckBtn').onclick = () => {
  if (!pendingMain || !pendingHq) return;
  draftMainNation = pendingMain;
  draftAllyNation = pendingAlly;
  draftHq = pendingHq;
  draftDeck = generateDefaultDeck(pendingMain, pendingAlly);
  updateCodexView();
  toast(`已套用默认卡组(${draftDeck.length} 张)`);
};

$('codexBtn').onclick = openCodex;
$('closeCodex').onclick = () => { commitDraftToMeta(false); meta.activeDeckIdx = editDeckIdx; $('codexModal').classList.remove('show'); };
$('codexModal').onclick = e => { if (e.target === $('codexModal')) { commitDraftToMeta(false); meta.activeDeckIdx = editDeckIdx; $('codexModal').classList.remove('show'); } };

function closeNationPickerMenu() {
  const existing = document.getElementById('nationPickerMenu');
  if (existing) existing.remove();
}

function showNationPickerMenu(anchorEl) {
  closeNationPickerMenu();
  const menu = document.createElement('div');
  menu.id = 'nationPickerMenu';
  menu.className = 'nation-picker-menu';
  NATION_ORDER.forEach(nid => {
    const btn = document.createElement('button');
    btn.className = 'nation-picker-btn';
    btn.textContent = NATIONS[nid].name;
    btn.onclick = () => { codexNationFilter = nid; closeNationPickerMenu(); renderCodex(); };
    menu.appendChild(btn);
  });
  const rect = anchorEl.getBoundingClientRect();
  menu.style.position = 'fixed';
  menu.style.left = rect.left + 'px';
  menu.style.top = (rect.bottom + 4) + 'px';
  document.body.appendChild(menu);
  setTimeout(() => {
    document.addEventListener('pointerdown', function onDoc(ev) {
      if (!menu.contains(ev.target) && ev.target !== anchorEl) {
        closeNationPickerMenu();
        document.removeEventListener('pointerdown', onDoc, true);
      }
    }, true);
  }, 0);
}

function renderNationFilter() {
  const cont = $('nationFilter');
  cont.innerHTML = '';

  const allBtn = document.createElement('button');
  const showingAll = codexNationFilter === 'all';
  const showingMain = codexNationFilter === 'main';
  allBtn.className = 'nation-tag' + ((showingAll || showingMain) ? ' active' : '');
  allBtn.textContent = showingAll ? '全部' : (showingMain ? '主+盟' : '全部');
  let lpTimer = null, lpFired = false;
  allBtn.addEventListener('pointerdown', e => {
    if (e.pointerType === 'mouse' && e.button !== 0) return;
    lpFired = false;
    lpTimer = setTimeout(() => { lpFired = true; showNationPickerMenu(allBtn); }, 500);
  });
  const cancelLp = () => { if (lpTimer) { clearTimeout(lpTimer); lpTimer = null; } };
  allBtn.addEventListener('pointerup', () => {
    cancelLp();
    if (lpFired) return;
    codexNationFilter = (codexNationFilter === 'all') ? 'main' : 'all';
    closeNationPickerMenu();
    renderCodex();
  });
  allBtn.addEventListener('pointerleave', cancelLp);
  allBtn.addEventListener('pointercancel', cancelLp);
  cont.appendChild(allBtn);

  if (!showingAll && !showingMain && NATIONS[codexNationFilter]) {
    const activeTag = document.createElement('button');
    activeTag.className = 'nation-tag active';
    activeTag.textContent = NATIONS[codexNationFilter].name;
    activeTag.onclick = () => { codexNationFilter = 'main'; closeNationPickerMenu(); renderCodex(); };
    cont.appendChild(activeTag);
  }
}

function renderCodex() {
  renderNationFilter();

  const mainCount = draftDeck.filter(id => CARD_DB[id] && CARD_DB[id].nation === draftMainNation).length;
  const allyCount = draftAllyNation
    ? draftDeck.filter(id => CARD_DB[id] && CARD_DB[id].nation === draftAllyNation).length
    : 0;
  const mainCap = draftAllyNation ? MAIN_CAP_WITH_ALLY : DECK_LIMIT;
  const allyCap = draftAllyNation ? ALLY_CAP : 0;

  $('mainCount').textContent = mainCount;
  $('mainCapText').textContent = mainCap;
  $('deckCount').textContent = draftDeck.length;

  const allyLabelEl = $('allyLabel');
  const allyNumEl = $('allyNum');
  if (draftAllyNation) {
    allyLabelEl.style.display = '';
    allyNumEl.style.display = '';
    $('allyCount').textContent = allyCount;
    $('allyCapText').textContent = allyCap;
  } else {
    allyLabelEl.style.display = 'none';
    allyNumEl.style.display = 'none';
  }

  const totalNumEl = $('totalNum');
  if (totalNumEl) totalNumEl.classList.toggle('warn', draftDeck.length < DECK_LIMIT);
  const mainEl = $('mainCount').parentElement;
  const allyEl = $('allyCount').parentElement;
  if (mainEl) mainEl.classList.toggle('warn', mainCount > mainCap);
  if (allyEl) allyEl.classList.toggle('warn', allyCount > allyCap);

  const grid = $('codexGrid');
  grid.innerHTML = '';
  const deckCounts = {};
  draftDeck.forEach(id => deckCounts[id] = (deckCounts[id] || 0) + 1);

  const showAll = codexNationFilter === 'all';
  const showMain = codexNationFilter === 'main';
  const onlyNation = (!showAll && !showMain) ? codexNationFilter : null;

  Object.keys(CARD_DB).forEach(cardId => {
    const def = CARD_DB[cardId];
    if (def.type === 'hq') return;

    if (onlyNation) {
      if (def.nation !== onlyNation) return;
    } else if (showMain) {
      if (def.nation !== draftMainNation && def.nation !== draftAllyNation) return;
    }

    const isFromMain = def.nation === draftMainNation;
    const isFromAlly = draftAllyNation && def.nation === draftAllyNation;
    const canAdd = isFromMain || isFromAlly;
    const owned = meta.ownedCards[cardId] || 0;
    const inDeck = deckCounts[cardId] || 0;

    const el = document.createElement('div');
    let cls = 'card ' + cardClassExtras(def) + rarityCls(def);
    if (owned <= 0) cls += ' not-owned';
    if (!canAdd) cls += ' locked';
    el.className = cls;
    el.innerHTML = cardInner(def);

    if (owned > 0) {
      const b = document.createElement('span');
      b.className = 'owned-badge';
      b.textContent = 'x' + owned;
      el.appendChild(b);
    }
    if (inDeck > 0) {
      const b = document.createElement('span');
      b.className = 'deck-badge';
      b.textContent = '组' + inDeck;
      el.appendChild(b);
    }

    bindCardInteractions(el, {
      single: () => addToDraft(cardId, canAdd),
      dbl: () => showCardDetail(cardId)
    });
    grid.appendChild(el);
  });
}

function switchEditDeck(i) {
  commitDraftToMeta(false);
  editDeckIdx = i;
  loadDeckIntoDraft(i);
  updateCodexView();
}
function commitDraftToMeta(showToast) {
  const name = ($('deckNameInput').value || '').trim() || `卡组 ${editDeckIdx + 1}`;
  const validCards = draftDeck.filter(id => {
    const def = CARD_DB[id];
    if (!def) return false;
    if (def.nation === draftMainNation) return true;
    if (draftAllyNation && def.nation === draftAllyNation) return true;
    return false;
  });
  meta.decks[editDeckIdx] = {
    name: name.slice(0, 12),
    mainNation: draftMainNation,
    allyNation: draftAllyNation,
    hq: draftHq,
    cards: validCards
  };
  if (showToast) toast(`卡组已保存(${validCards.length} 张)`);
}
function addToDraft(cardId, canAdd) {
  if (!canAdd) { toast('该卡不在主国或盟国中,无法加入'); playDenySound(); return; }
  const def = CARD_DB[cardId];
  const isFromMain = def.nation === draftMainNation;
  const isFromAlly = draftAllyNation && def.nation === draftAllyNation;
  const mainCount = draftDeck.filter(id => CARD_DB[id] && CARD_DB[id].nation === draftMainNation).length;
  const allyCount = draftAllyNation
    ? draftDeck.filter(id => CARD_DB[id] && CARD_DB[id].nation === draftAllyNation).length
    : 0;

  const mainCap = draftAllyNation ? MAIN_CAP_WITH_ALLY : DECK_LIMIT;
  const allyCap = draftAllyNation ? ALLY_CAP : 0;

  if (isFromMain && mainCount >= mainCap) { toast(`主国已满 ${mainCap} 张`); playDenySound(); return; }
  if (isFromAlly && allyCount >= allyCap) { toast(`盟国已满 ${allyCap} 张`); playDenySound(); return; }
  if (draftDeck.length >= DECK_LIMIT) { toast('卡组已满 40 张'); playDenySound(); return; }

  const owned = meta.ownedCards[cardId] || 0;
  if (owned <= 0) { toast('未拥有这张卡'); playDenySound(); return; }
  const inDeck = draftDeck.filter(id => id === cardId).length;
  if (inDeck >= owned) { toast('没有更多这张卡了'); playDenySound(); return; }

  draftDeck.push(cardId);
  renderCodex();
}
$('clearDeckBtn').onclick = () => { draftDeck = []; renderCodex(); toast('已清空当前卡组'); };
$('saveDeckBtn').onclick = () => { commitDraftToMeta(true); renderCodex(); };
$('changeNationBtn').onclick = () => {
  if (draftDeck.length > 0) { draftDeck = []; toast('已清空卡组,请重新选择国家与总部'); }
  draftMainNation = null;
  draftAllyNation = null;
  draftHq = null;
  pendingMain = null; pendingAlly = null; pendingHq = null;
  updateCodexView();
};

/* ==================== 存档 UI ==================== */
function saveStatus(msg) { const el = $('saveStatus'); el.textContent = msg; clearTimeout(saveStatus.t); saveStatus.t = setTimeout(() => { el.textContent = ''; }, 2200); }
$('closeModal').onclick = () => $('modal').classList.remove('show');
$('modal').onclick = e => { if (e.target === $('modal')) $('modal').classList.remove('show'); };

$('exportBtn').onclick = () => {
  const pwd = $('pwdInput').value;
  const payload = { v: 6, game: gameState, meta: meta };
  $('saveCode').value = Save.exportCode(payload, pwd);
  $('saveCode').select();
  saveStatus('存档已生成,请复制保存');
};
$('importBtn').onclick = () => {
  const code = $('saveCode').value.trim();
  if (!code) { saveStatus('请先粘贴存档码'); return; }
  const pwd = $('pwdInput').value;
  const res = Save.importCode(code, pwd);
  if (res.error) { saveStatus(res.error); return; }
  const data = res.data;
  if (data && (data.v === 2 || data.v === 3 || data.v === 4 || data.v === 5 || data.v === 6) && data.game && data.meta) {
    if (!isValidState(data.game)) { saveStatus('存档内容无效'); return; }
    if (typeof data.meta.coins !== 'number') { saveStatus('存档内容无效'); return; }
    gameState = data.game;
    meta = migrateMeta(data.meta);
  } else if (isValidState(data)) {
    gameState = data;
  } else { saveStatus('存档内容无效'); return; }
  if (gameState.player && typeof gameState.player.counter === 'undefined') gameState.player.counter = null;
  if (gameState.enemy && typeof gameState.enemy.counter === 'undefined') gameState.enemy.counter = null;
  gameState.active = 'player'; gameState.over = null;
  gameState.turn = gameState.turn || 1;
  gameState.difficulty = gameState.difficulty || 'normal';
  selectedCard = null; selectedUnit = null;
  $('modal').classList.remove('show');
  enterGame(); render(); updateCoinDisplays();
  toast('读取成功');
};
$('newGameBtn').onclick = () => {
  gameState = newGame('normal');
  selectedCard = null; selectedUnit = null;
  $('modal').classList.remove('show');
  enterGame(); render();
  toast('新游戏已开始');
};
$('overlayBtn').onclick = () => {
  const diff = (gameState && gameState.difficulty) || 'normal';
  gameState = newGame(diff);
  selectedCard = null; selectedUnit = null;
  $('overlay').classList.remove('show');
  render();
};

function isValidState(s) {
  if (!s || typeof s !== 'object') return false;
  if (typeof s.turn !== 'number') return false;
  if (!s.lanes || typeof s.lanes !== 'object') return false;
  for (const side of ['player', 'enemy']) {
    const x = s[side];
    if (!x || typeof x !== 'object') return false;
    if (typeof x.hp !== 'number' || typeof x.maxHp !== 'number') return false;
    if (!Array.isArray(x.hand) || !Array.isArray(x.deck)) return false;
    if (x.hand.concat(x.deck).some(id => !CARD_DB[id])) return false;
  }
  for (const laneName of ['playerHome', 'contested', 'enemyHome']) {
    const lane = s.lanes[laneName];
    if (!Array.isArray(lane)) return false;
    for (const u of lane) if (u && !CARD_DB[u.id]) return false;
  }
  return true;
}

meta = migrateMeta(meta);
updateCoinDisplays();
showLobby();
</script>
</body>
</html>

Game Source: 指挥官 · Commander

Creator: SwiftGalaxy49

Libraries: none

Complexity: complex (4684 lines, 366.2 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: commander-swiftgalaxy49" to link back to the original. Then publish at arcadelab.ai/publish.