feat(@projects/@magic-civilization): add combat preview modal design

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-04-26 15:21:52 -07:00
parent 151b0d4360
commit 4b45e38d52
2 changed files with 1006 additions and 0 deletions

View file

@ -0,0 +1,518 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Age of Dwarves — Combat Preview Sketch</title>
<link href="https://fonts.googleapis.com/css2?family=Grenze+Gotisch:wght@900&family=Bitter:wght@700&display=swap" rel="stylesheet">
<style>
:root {
--bg: #171219;
--panel: #17121e;
--surface: #221a14;
--btn: #1f1733;
--title: #f2d973;
--primary: #e0d8c8;
--secondary: #bfb7a6;
--muted: #b2b2b2;
--gold: #d9a020;
--gold-b: #d9b33f;
--science: #66bfff;
--sage: #66b866;
--neg: #d95940;
--warn: #e69933;
--border: #73591fcc;
--font-h: 'Grenze Gotisch', serif;
--font-b: 'Bitter', serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--bg);
color: var(--primary);
font-family: var(--font-b);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
}
/* ── MODAL SHELL ── */
.modal-scrim {
position: fixed; inset: 0;
background: rgba(0,0,0,0.62);
display: flex; align-items: center; justify-content: center;
}
/* ── COMBAT CARD ── */
.combat-card {
width: 760px;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 4px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0,0,0,0.8);
}
/* Header */
.combat-header {
background: #1a1228;
border-bottom: 2px solid var(--border);
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.combat-title {
font-family: var(--font-h);
font-size: 24px;
color: var(--title);
letter-spacing: 0.04em;
}
.combat-subtitle {
font-size: 12px;
color: var(--secondary);
margin-top: 2px;
}
.close-btn {
width: 32px; height: 32px;
background: var(--btn);
border: 1px solid var(--border);
border-radius: 3px;
display: flex; align-items: center; justify-content: center;
color: var(--muted); font-size: 16px; cursor: pointer;
}
/* VS Row */
.vs-row {
display: grid;
grid-template-columns: 1fr 60px 1fr;
gap: 0;
padding: 24px 24px 0;
}
.combatant {
display: flex;
flex-direction: column;
align-items: center;
gap: 0;
}
.unit-portrait {
width: 80px; height: 80px;
border-radius: 50%;
border: 3px solid;
display: flex; align-items: center; justify-content: center;
font-size: 36px;
background: radial-gradient(ellipse at 40% 40%, #2a1a06, #0e0a17);
margin-bottom: 10px;
box-shadow: 0 0 20px rgba(0,0,0,0.6);
}
.unit-name {
font-family: var(--font-h);
font-size: 18px;
color: var(--title);
letter-spacing: 0.04em;
text-align: center;
}
.unit-type {
font-size: 11px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.08em;
margin-top: 2px;
text-align: center;
}
.unit-clan {
font-size: 12px;
color: var(--secondary);
margin-top: 4px;
}
.vs-badge {
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-h);
font-size: 28px;
color: var(--neg);
letter-spacing: 0.04em;
padding-top: 20px;
}
/* Stat bars */
.stat-block {
width: 100%;
margin-top: 16px;
}
.stat-line {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 6px;
}
.stat-line-label {
font-size: 11px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.06em;
width: 70px;
flex-shrink: 0;
}
.stat-bar-track {
flex: 1;
height: 6px;
background: #ffffff18;
border-radius: 2px;
overflow: hidden;
}
.stat-bar-fill { height: 100%; border-radius: 2px; }
.stat-line-val {
font-size: 13px;
font-weight: bold;
font-family: monospace;
width: 32px;
text-align: right;
flex-shrink: 0;
}
/* Modifiers */
.modifiers {
margin-top: 12px;
display: flex;
flex-direction: column;
gap: 3px;
}
.mod-row {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 11px;
color: var(--secondary);
padding: 2px 0;
}
.mod-val { font-family: monospace; font-weight: bold; }
.mod-pos { color: var(--sage); }
.mod-neg { color: var(--neg); }
.mod-neutral { color: var(--muted); }
/* Dividers */
.divider { border: none; border-top: 1px solid #73591f33; margin: 12px 0; }
/* ── OUTCOME SECTION ── */
.outcome-section {
padding: 20px 24px;
border-top: 1px solid #73591f33;
margin-top: 20px;
}
.outcome-label {
font-size: 11px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.1em;
text-align: center;
margin-bottom: 14px;
}
/* Probability bar */
.prob-bar-outer {
height: 32px;
border-radius: 3px;
overflow: hidden;
display: flex;
position: relative;
margin-bottom: 8px;
}
.prob-attacker {
background: linear-gradient(90deg, #d9594066, #d9594088);
border-right: 2px solid var(--neg);
display: flex; align-items: center;
padding: 0 10px;
font-size: 13px;
font-weight: bold;
color: var(--neg);
}
.prob-defender {
flex: 1;
background: linear-gradient(90deg, #66b86633, #66b86688);
border-left: 2px solid var(--sage);
display: flex; align-items: center; justify-content: flex-end;
padding: 0 10px;
font-size: 13px;
font-weight: bold;
color: var(--sage);
}
.prob-center {
position: absolute;
top: 50%; left: 50%; transform: translate(-50%, -50%);
font-size: 12px;
color: var(--muted);
background: var(--panel);
padding: 2px 8px;
border-radius: 2px;
border: 1px solid var(--border);
white-space: nowrap;
}
.prob-labels {
display: flex;
justify-content: space-between;
font-size: 11px;
color: var(--muted);
margin-bottom: 16px;
}
/* Expected damage */
.expected-damage {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 16px;
align-items: center;
margin-bottom: 16px;
}
.dmg-block {
background: rgba(31,23,51,0.6);
border: 1px solid var(--border);
border-radius: 3px;
padding: 10px 14px;
text-align: center;
}
.dmg-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 4px; }
.dmg-val { font-size: 22px; font-weight: bold; font-family: monospace; }
.dmg-sub { font-size: 11px; color: var(--muted); margin-top: 2px; }
.vs-arrow { text-align: center; font-size: 20px; color: var(--muted); }
/* Promotions */
.promo-section {
text-align: center;
font-size: 12px;
color: var(--secondary);
margin-bottom: 12px;
}
.promo-badge {
display: inline-block;
background: #1a1208;
border: 1px solid var(--gold);
border-radius: 2px;
padding: 3px 8px;
font-size: 11px;
color: var(--gold);
margin: 2px;
}
/* Action buttons */
.action-row {
display: flex;
gap: 10px;
padding: 16px 24px;
border-top: 1px solid #73591f33;
background: rgba(10,8,16,0.5);
}
.btn-attack {
flex: 1;
font-family: var(--font-h);
font-size: 20px;
color: var(--neg);
background: #3d0f08;
border: 2px solid var(--neg);
border-radius: 3px;
padding: 12px;
cursor: pointer;
letter-spacing: 0.06em;
text-align: center;
transition: all 150ms ease;
}
.btn-attack:hover { background: #5a1510; }
.btn-cancel {
font-family: var(--font-b);
font-size: 15px;
font-weight: 700;
color: var(--muted);
background: var(--btn);
border: 1px solid var(--border);
border-radius: 3px;
padding: 12px 24px;
cursor: pointer;
transition: all 150ms ease;
}
.btn-cancel:hover { color: var(--primary); border-color: var(--gold-b); }
.flank-notice {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: var(--warn);
background: #1a1000;
border: 1px solid #e6993344;
border-radius: 3px;
padding: 8px 14px;
margin: 0 24px;
}
</style>
</head>
<body>
<div class="modal-scrim">
<div class="combat-card">
<!-- ── HEADER ── -->
<div class="combat-header">
<div>
<div class="combat-title">Combat Preview</div>
<div class="combat-subtitle">⛰ Plains (2, 4) · Melee attack</div>
</div>
<div class="close-btn"></div>
</div>
<!-- ── VS ROW ── -->
<div class="vs-row">
<!-- ATTACKER -->
<div class="combatant">
<div class="unit-portrait" style="border-color:#3366ff;box-shadow:0 0 20px #3366ff33,0 0 40px #000a"></div>
<div class="unit-name">Iron Warrior</div>
<div class="unit-type">Melee Infantry</div>
<div class="unit-clan" style="color:#6699ff">Stoneguard Clan (You)</div>
<div class="stat-block">
<div class="stat-line">
<span class="stat-line-label">Attack</span>
<div class="stat-bar-track"><div class="stat-bar-fill" style="width:72%;background:#d95940"></div></div>
<span class="stat-line-val" style="color:#d95940">18</span>
</div>
<div class="stat-line">
<span class="stat-line-label">Defense</span>
<div class="stat-bar-track"><div class="stat-bar-fill" style="width:50%;background:#66bfff"></div></div>
<span class="stat-line-val" style="color:#66bfff">12</span>
</div>
<div class="stat-line">
<span class="stat-line-label">HP</span>
<div class="stat-bar-track"><div class="stat-bar-fill" style="width:85%;background:#66b866"></div></div>
<span class="stat-line-val" style="color:#66b866">68</span>
</div>
<div class="stat-line">
<span class="stat-line-label">XP</span>
<div class="stat-bar-track"><div class="stat-bar-fill" style="width:60%;background:#d9a020"></div></div>
<span class="stat-line-val" style="color:#d9a020">24</span>
</div>
</div>
<div class="modifiers">
<hr class="divider">
<div class="mod-row"><span>Base attack</span><span class="mod-val mod-neutral">18</span></div>
<div class="mod-row"><span>★ Strength I</span><span class="mod-val mod-pos">+2</span></div>
<div class="mod-row"><span>★ Flanking</span><span class="mod-val mod-pos">+15%</span></div>
<div class="mod-row"><span>Wounded (85%)</span><span class="mod-val mod-neutral"></span></div>
<hr class="divider">
<div class="mod-row" style="font-weight:bold"><span>Effective attack</span><span class="mod-val" style="color:#d9a020">21.7</span></div>
</div>
</div>
<!-- VS BADGE -->
<div class="vs-badge">VS</div>
<!-- DEFENDER -->
<div class="combatant">
<div class="unit-portrait" style="border-color:#e63333;box-shadow:0 0 20px #e6333333,0 0 40px #000a">🛡</div>
<div class="unit-name">Bronze Guard</div>
<div class="unit-type">Melee Infantry</div>
<div class="unit-clan" style="color:#ff8888">Emberfall Clan</div>
<div class="stat-block">
<div class="stat-line">
<span class="stat-line-label">Attack</span>
<div class="stat-bar-track"><div class="stat-bar-fill" style="width:56%;background:#d95940"></div></div>
<span class="stat-line-val" style="color:#d95940">14</span>
</div>
<div class="stat-line">
<span class="stat-line-label">Defense</span>
<div class="stat-bar-track"><div class="stat-bar-fill" style="width:72%;background:#66bfff"></div></div>
<span class="stat-line-val" style="color:#66bfff">18</span>
</div>
<div class="stat-line">
<span class="stat-line-label">HP</span>
<div class="stat-bar-track"><div class="stat-bar-fill" style="width:100%;background:#66b866"></div></div>
<span class="stat-line-val" style="color:#66b866">80</span>
</div>
<div class="stat-line">
<span class="stat-line-label">XP</span>
<div class="stat-bar-track"><div class="stat-bar-fill" style="width:30%;background:#d9a020"></div></div>
<span class="stat-line-val" style="color:#d9a020">12</span>
</div>
</div>
<div class="modifiers">
<hr class="divider">
<div class="mod-row"><span>Base defense</span><span class="mod-val mod-neutral">18</span></div>
<div class="mod-row"><span>Plains terrain</span><span class="mod-val mod-neutral">+0%</span></div>
<div class="mod-row"><span>Fortified (1t)</span><span class="mod-val mod-pos">+10%</span></div>
<div class="mod-row"><span>Outnumbered</span><span class="mod-val mod-neg">10%</span></div>
<hr class="divider">
<div class="mod-row" style="font-weight:bold"><span>Effective defense</span><span class="mod-val" style="color:#d9a020">18.0</span></div>
</div>
</div>
</div>
<!-- ── FLANKING NOTICE ── -->
<div class="flank-notice" style="margin-top:16px">
⚠ Flanking bonus active — 2nd Stoneguard unit adjacent gives +15% attack
</div>
<!-- ── OUTCOME ── -->
<div class="outcome-section">
<div class="outcome-label">Predicted Outcome</div>
<!-- Win probability bar -->
<div class="prob-bar-outer">
<div class="prob-attacker" style="width:62%">62%</div>
<div class="prob-defender">38%</div>
<div class="prob-center">win probability</div>
</div>
<div class="prob-labels">
<span style="color:#d95940">Attacker wins</span>
<span style="color:#66b866">Defender survives</span>
</div>
<!-- Expected damage -->
<div class="expected-damage">
<div class="dmg-block">
<div class="dmg-label">Attacker takes</div>
<div class="dmg-val" style="color:#d95940">22</div>
<div class="dmg-sub">HP · 46 remain</div>
</div>
<div class="vs-arrow"></div>
<div class="dmg-block">
<div class="dmg-label">Defender takes</div>
<div class="dmg-val" style="color:#66b866">34</div>
<div class="dmg-sub">HP · 46 remain</div>
</div>
</div>
<!-- Promotions available -->
<div class="promo-section">
If victorious, Iron Warrior gains enough XP for:
<div style="margin-top:6px">
<div class="promo-badge">★★ Combat II</div>
<div class="promo-badge">★★ City Raider</div>
<div class="promo-badge">★★ Shock</div>
</div>
</div>
</div>
<!-- ── ACTIONS ── -->
<div class="action-row">
<div class="btn-attack">⚔ Confirm Attack</div>
<div class="btn-cancel">Cancel</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,488 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Age of Dwarves — Promotion Picker Sketch</title>
<link href="https://fonts.googleapis.com/css2?family=Grenze+Gotisch:wght@900&family=Bitter:wght@700&display=swap" rel="stylesheet">
<style>
:root {
--bg: #171219;
--panel: #17121e;
--surface: #221a14;
--btn: #1f1733;
--title: #f2d973;
--primary: #e0d8c8;
--secondary: #bfb7a6;
--muted: #b2b2b2;
--gold: #d9a020;
--gold-b: #d9b33f;
--science: #66bfff;
--sage: #66b866;
--neg: #d95940;
--border: #73591fcc;
--font-h: 'Grenze Gotisch', serif;
--font-b: 'Bitter', serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: rgba(0,0,0,0.7);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
font-family: var(--font-b);
}
/* Background map bleed */
body::before {
content: '';
position: fixed; inset: 0;
background:
radial-gradient(ellipse at 30% 60%, #1a3319 0%, transparent 50%),
radial-gradient(ellipse at 70% 30%, #19231a 0%, transparent 40%),
#0d1208;
z-index: -1;
filter: blur(2px);
}
/* ── MODAL ── */
.modal {
width: 660px;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 4px;
box-shadow: 0 24px 80px rgba(0,0,0,0.9), 0 0 0 1px #73591f22;
overflow: hidden;
}
/* Header */
.modal-header {
background: linear-gradient(180deg, #2a1a06 0%, #1a1208 100%);
border-bottom: 2px solid var(--gold);
padding: 16px 20px;
display: flex;
align-items: center;
gap: 16px;
}
.unit-portrait {
width: 56px; height: 56px;
border-radius: 50%;
border: 2px solid var(--gold);
background: radial-gradient(ellipse at 40% 40%, #2a1a06, #0e0a17);
display: flex; align-items: center; justify-content: center;
font-size: 26px;
box-shadow: 0 0 16px #d9a02033;
flex-shrink: 0;
}
.header-info { flex: 1; }
.header-title {
font-family: var(--font-h);
font-size: 22px;
color: var(--title);
letter-spacing: 0.04em;
margin-bottom: 2px;
}
.header-sub { font-size: 12px; color: var(--secondary); }
.header-xp {
text-align: right;
font-size: 12px;
color: var(--muted);
}
.header-xp-val {
font-size: 20px;
font-weight: bold;
color: var(--gold);
font-family: monospace;
display: block;
margin-bottom: 2px;
}
/* Already-earned promotions */
.earned-strip {
background: rgba(10,8,16,0.6);
border-bottom: 1px solid #73591f33;
padding: 8px 20px;
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.earned-label {
font-size: 11px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.08em;
flex-shrink: 0;
}
.promo-tag {
display: flex;
align-items: center;
gap: 4px;
background: #1a1208;
border: 1px solid var(--gold);
border-radius: 2px;
padding: 3px 8px;
font-size: 11px;
color: var(--gold);
}
/* Section label */
.section-label {
padding: 14px 20px 8px;
font-size: 11px;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.1em;
}
/* ── PROMOTION GRID ── */
.promo-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
padding: 0 20px 16px;
}
.promo-card {
background: var(--btn);
border: 1px solid #73591f88;
border-radius: 3px;
padding: 12px;
cursor: pointer;
transition: all 150ms ease;
position: relative;
overflow: hidden;
}
.promo-card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 2px;
background: transparent;
transition: background 150ms ease;
}
.promo-card:hover {
border-color: var(--gold-b);
background: #2a1a0a;
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0,0,0,0.6);
}
.promo-card:hover::before { background: var(--gold); }
.promo-card.selected {
border-color: var(--gold);
background: #2a1a06;
box-shadow: 0 0 20px #d9a02022;
}
.promo-card.selected::before { background: var(--gold); }
.promo-card.locked {
opacity: 0.4;
cursor: not-allowed;
filter: grayscale(0.4);
}
.promo-card.locked:hover { transform: none; box-shadow: none; }
.promo-card.combat { border-top: 2px solid #d9594066; }
.promo-card.combat.selected { border-top-color: var(--neg); }
.promo-card.support { border-top: 2px solid #66b86666; }
.promo-card.support.selected { border-top-color: var(--sage); }
.promo-card.special { border-top: 2px solid #66bfff66; }
.promo-card.special.selected { border-top-color: var(--science); }
.promo-card-top {
display: flex;
align-items: flex-start;
gap: 8px;
margin-bottom: 8px;
}
.promo-icon { font-size: 22px; flex-shrink: 0; }
.promo-name {
font-size: 13px;
font-weight: bold;
color: var(--primary);
line-height: 1.2;
}
.promo-rank {
display: flex;
gap: 2px;
margin-top: 2px;
}
.star { color: var(--gold); font-size: 10px; }
.star.empty { color: #73591f44; }
.promo-type {
margin-left: auto;
font-size: 9px;
text-transform: uppercase;
letter-spacing: 0.08em;
padding: 2px 5px;
border-radius: 2px;
flex-shrink: 0;
}
.type-combat { background: #d9594022; color: #d9594099; border: 1px solid #d9594033; }
.type-support { background: #66b86622; color: #66b86699; border: 1px solid #66b86633; }
.type-special { background: #66bfff22; color: #66bfff99; border: 1px solid #66bfff33; }
.promo-desc {
font-size: 11px;
color: var(--secondary);
line-height: 1.4;
margin-bottom: 6px;
}
.promo-effect {
font-size: 11px;
font-family: monospace;
font-weight: bold;
}
.selected-check {
position: absolute;
top: 8px; right: 8px;
width: 18px; height: 18px;
border-radius: 50%;
background: var(--gold);
display: flex; align-items: center; justify-content: center;
font-size: 11px;
color: #000;
}
/* Lock reason */
.lock-reason {
font-size: 10px;
color: var(--neg);
margin-top: 4px;
display: flex;
align-items: center;
gap: 4px;
}
/* ── FOOTER ── */
.modal-footer {
border-top: 1px solid var(--border);
padding: 14px 20px;
display: flex;
align-items: center;
gap: 10px;
background: rgba(10,8,16,0.5);
}
.selected-summary {
flex: 1;
font-size: 13px;
color: var(--secondary);
}
.selected-name { color: var(--title); font-weight: bold; }
.btn-confirm {
font-family: var(--font-h);
font-size: 18px;
color: var(--title);
background: #2a1a06;
border: 2px solid var(--gold);
border-radius: 3px;
padding: 10px 28px;
cursor: pointer;
letter-spacing: 0.05em;
transition: all 150ms ease;
}
.btn-confirm:hover { background: #3d2608; border-color: var(--gold-b); }
.btn-cancel {
font-family: var(--font-b);
font-size: 14px;
font-weight: 700;
color: var(--muted);
background: var(--btn);
border: 1px solid var(--border);
border-radius: 3px;
padding: 10px 18px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="modal">
<!-- ── HEADER ── -->
<div class="modal-header">
<div class="unit-portrait"></div>
<div class="header-info">
<div class="header-title">Promotion Available</div>
<div class="header-sub">Iron Warrior · Melee Infantry · Stoneguard Clan</div>
</div>
<div class="header-xp">
<span class="header-xp-val">★★</span>
Rank 2 · 48 XP
</div>
</div>
<!-- ── EARNED ── -->
<div class="earned-strip">
<span class="earned-label">Earned:</span>
<div class="promo-tag">★ Strength I</div>
<div class="promo-tag">★ Flanking</div>
</div>
<!-- ── GRID ── -->
<div class="section-label">Choose one promotion</div>
<div class="promo-grid">
<!-- Combat promos -->
<div class="promo-card combat selected">
<div class="selected-check"></div>
<div class="promo-card-top">
<div class="promo-icon"></div>
<div>
<div class="promo-name">Combat II</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-combat">Combat</div>
</div>
<div class="promo-desc">Increases base combat strength when attacking.</div>
<div class="promo-effect" style="color:#d95940">+10% attack strength</div>
</div>
<div class="promo-card combat">
<div class="promo-card-top">
<div class="promo-icon">🗡</div>
<div>
<div class="promo-name">Shock</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-combat">Combat</div>
</div>
<div class="promo-desc">Bonus strength when attacking units in open terrain.</div>
<div class="promo-effect" style="color:#d95940">+15% vs units on plains / desert</div>
</div>
<div class="promo-card combat">
<div class="promo-card-top">
<div class="promo-icon">🏰</div>
<div>
<div class="promo-name">City Raider</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-combat">Combat</div>
</div>
<div class="promo-desc">Specialised for assaulting fortified positions and cities.</div>
<div class="promo-effect" style="color:#d95940">+20% vs fortified / city units</div>
</div>
<!-- Support promos -->
<div class="promo-card support">
<div class="promo-card-top">
<div class="promo-icon">🛡</div>
<div>
<div class="promo-name">Stalwart</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-support">Defense</div>
</div>
<div class="promo-desc">Hardens the unit against incoming attacks.</div>
<div class="promo-effect" style="color:#66b866">+10% defense strength</div>
</div>
<div class="promo-card support">
<div class="promo-card-top">
<div class="promo-icon"></div>
<div>
<div class="promo-name">Medic I</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-support">Support</div>
</div>
<div class="promo-desc">Unit and adjacent friendly units heal faster each turn.</div>
<div class="promo-effect" style="color:#66b866">+5 HP healed / turn (nearby units +2)</div>
</div>
<div class="promo-card special locked">
<div class="promo-card-top">
<div class="promo-icon">💀</div>
<div>
<div class="promo-name">March</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-special">Special</div>
</div>
<div class="promo-desc">Unit heals even when it attacks during a turn.</div>
<div class="promo-effect" style="color:#66bfff">Heal 10 HP per turn even when moving</div>
<div class="lock-reason">🔒 Requires: Medic I</div>
</div>
<!-- Row 3 -->
<div class="promo-card special">
<div class="promo-card-top">
<div class="promo-icon"></div>
<div>
<div class="promo-name">Blitz</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-special">Special</div>
</div>
<div class="promo-desc">May attack more than once per turn if first strike kills.</div>
<div class="promo-effect" style="color:#66bfff">Extra attack on kill</div>
</div>
<div class="promo-card combat locked">
<div class="promo-card-top">
<div class="promo-icon"></div>
<div>
<div class="promo-name">Mountaineer</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-combat">Terrain</div>
</div>
<div class="promo-desc">Excels in rough highland terrain.</div>
<div class="promo-effect" style="color:#d95940">+25% in hills / mountains</div>
<div class="lock-reason">🔒 Requires: Combat II</div>
</div>
<div class="promo-card support">
<div class="promo-card-top">
<div class="promo-icon">👁</div>
<div>
<div class="promo-name">Scout</div>
<div class="promo-rank">
<span class="star"></span><span class="star"></span><span class="star empty"></span>
</div>
</div>
<div class="promo-type type-support">Recon</div>
</div>
<div class="promo-desc">Extends visibility range and reveals more fog of war.</div>
<div class="promo-effect" style="color:#66b866">+1 vision range · reveals terrain faster</div>
</div>
</div>
<!-- ── FOOTER ── -->
<div class="modal-footer">
<div class="selected-summary">
Selected: <span class="selected-name">Combat II</span>
<span style="color:var(--muted)"> · +10% attack strength</span>
</div>
<div class="btn-cancel">Back</div>
<div class="btn-confirm">Promote ★★</div>
</div>
</div>
</body>
</html>