feat: stratagem icons, session summary, queue preview, UX polish

- Download 65 SVG icons from community repo (scripts/download-icons.js)
- Gold CSS filter on all icons to match game theme
- Session summary modal with score/accuracy/top stratagems
- Queue preview strip (next 3 stratagems with icons)
- Score popup animation, icon shake on wrong input
- Icons in history, leaderboard, and best-per-stratagem tables
- server.js: icon fields on all stratagems, ELO in lobby-update WS events
This commit is contained in:
Jeremy Brandenburger
2026-03-31 08:48:56 +02:00
parent 0d971745a6
commit 2d27d9fe4d
72 changed files with 2280 additions and 372 deletions
+23
View File
@@ -1,5 +1,28 @@
# Changelog helldivers-trainer
## [2.1.0] 2026-03-31
### Added
- **Stratagem icons**: 65 SVG icons downloaded from community icon set, served as static files under `/icons/`; icon download script at `scripts/download-icons.js`
- **Gold CSS filter** on all stratagem icons to match the game's yellow accent theme
- **Session summary modal**: opens after stopping practice or finishing a drill/speedrun — shows score, completed count, accuracy, best time, and top 5 stratagems
- **Queue preview strip**: shows next 3 upcoming stratagems (with icons) below the active stratagem
- **Score popup animation**: floating `+N pts` text appears on every correct completion
- **Shake animation on wrong input**: stratagem icon shakes on incorrect arrow key
- **Icon complete pulse**: stratagem icon scales + brightens when sequence is completed correctly
- **ELO rank icon** in post-match result header (matches rank tier badge)
- **Inline icons** in history table rows, best-per-stratagem table, and leaderboard
- `scripts/download-icons.js` — automated icon fetcher from GitHub community SVG repo
### Changed
- `index.html` fully rewritten: new elements for icon display, queue, score popup, session summary modal
- `app.js` fully rewritten (~1100 lines): icon helpers, queue builder, popup system, session stats, improved match/lobby flows
- `server.js` STRATAGEMS array: all 65 entries now have `icon` field (or `null` for missing ones)
- `broadcastLobbyUpdate()` now sends `[{name, elo, rank}]` objects with CSS-safe rank labels
- `challenge-received` WS event now includes challenger ELO for display in challenge modal
---
## [2.0.0] 2026-03-30
### Added
+1015 -223
View File
File diff suppressed because it is too large Load Diff
+67
View File
@@ -0,0 +1,67 @@
{
"Reinforce": "/icons/reinforce.svg",
"Resupply": "/icons/resupply.svg",
"SOS Beacon": "/icons/sos_beacon.svg",
"Hellbomb": "/icons/hellbomb.svg",
"SEAF Artillery": "/icons/seaf_artillery.svg",
"Upload Data": "/icons/upload_data.svg",
"Prospecting Drill": "/icons/prospecting_drill.svg",
"Orbital Illumination Flare": "/icons/orbital_illumination_flare.svg",
"Orbital Gatling Barrage": "/icons/orbital_gatling_barrage.svg",
"Orbital Airburst Strike": "/icons/orbital_airburst_strike.svg",
"Orbital 120MM HE Barrage": "/icons/orbital_120mm_he_barrage.svg",
"Orbital 380MM HE Barrage": "/icons/orbital_380mm_he_barrage.svg",
"Orbital Walking Barrage": "/icons/orbital_walking_barrage.svg",
"Orbital Laser": "/icons/orbital_laser.svg",
"Orbital Railcannon Strike": "/icons/orbital_railcannon_strike.svg",
"Orbital Precision Strike": "/icons/orbital_precision_strike.svg",
"Orbital Gas Strike": "/icons/orbital_gas_strike.svg",
"Orbital EMS Strike": "/icons/orbital_ems_strike.svg",
"Orbital Smoke Strike": "/icons/orbital_smoke_strike.svg",
"Tesla Tower": "/icons/tesla_tower.svg",
"Shield Generator Relay": "/icons/shield_generator_relay.svg",
"HMG Emplacement": "/icons/hmg_emplacement.svg",
"Eagle Strafing Run": "/icons/eagle_strafing_run.svg",
"Eagle Airstrike": "/icons/eagle_airstrike.svg",
"Eagle Cluster Bomb": "/icons/eagle_cluster_bomb.svg",
"Eagle Napalm Airstrike": "/icons/eagle_napalm_airstrike.svg",
"LIFT-850 Jump Pack": "/icons/lift_850_jump_pack.svg",
"Eagle Smoke Strike": "/icons/eagle_smoke_strike.svg",
"Eagle 110MM Rocket Pods": "/icons/eagle_110mm_rocket_pods.svg",
"Eagle 500KG Bomb": "/icons/eagle_500kg_bomb.svg",
"Eagle Rearm": "/icons/eagle_rearm.svg",
"Machine Gun": "/icons/machine_gun.svg",
"Anti-Materiel Rifle": "/icons/anti_materiel_rifle.svg",
"Stalwart": "/icons/stalwart.svg",
"Expendable Anti-Tank": "/icons/expendable_anti_tank.svg",
"Recoilless Rifle": "/icons/recoilless_rifle.svg",
"Flamethrower": "/icons/flamethrower.svg",
"Autocannon": "/icons/autocannon.svg",
"Heavy Machine Gun": "/icons/heavy_machine_gun.svg",
"Airburst Rocket Launcher": "/icons/airburst_rocket_launcher.svg",
"Commando": "/icons/commando.svg",
"Railgun": "/icons/railgun.svg",
"Spear": "/icons/spear.svg",
"Quasar Cannon": "/icons/quasar_cannon.svg",
"Arc Thrower": "/icons/arc_thrower.svg",
"Laser Cannon": "/icons/laser_cannon.svg",
"Grenade Launcher": "/icons/grenade_launcher.svg",
"Supply Pack": "/icons/supply_pack.svg",
"Guard Dog Rover": "/icons/guard_dog_rover.svg",
"Ballistic Shield Backpack": "/icons/ballistic_shield_backpack.svg",
"Shield Generator Pack": "/icons/shield_generator_pack.svg",
"Anti-Personnel Minefield": "/icons/anti_personnel_minefield.svg",
"Incendiary Mines": "/icons/incendiary_mines.svg",
"Anti-Tank Mines": "/icons/anti_tank_mines.svg",
"Machine Gun Sentry": "/icons/machine_gun_sentry.svg",
"Gatling Sentry": "/icons/gatling_sentry.svg",
"Mortar Sentry": "/icons/mortar_sentry.svg",
"Guard Dog": "/icons/guard_dog.svg",
"Autocannon Sentry": "/icons/autocannon_sentry.svg",
"Rocket Sentry": "/icons/rocket_sentry.svg",
"EMS Mortar Sentry": "/icons/ems_mortar_sentry.svg",
"Patriot Exosuit": "/icons/patriot_exosuit.svg",
"Emancipator Exosuit": "/icons/emancipator_exosuit.svg",
"Directional Shield": "/icons/directional_shield.svg",
"Anti-Tank Emplacement": "/icons/anti_tank_emplacement.svg"
}
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126"><g><path d="M29.227 20.952A18.825 18.825 0 1 1 10.4 39.778a18.825 18.825 0 0 1 18.827-18.826Zm0 2.121a16.7 16.7 0 1 1-16.7 16.7 16.7 16.7 0 0 1 16.7-16.7Z" fill="#fff" fill-rule="evenodd"/><path d="M29.366 26.681a12.776 12.776 0 1 1-12.76 12.776 12.768 12.768 0 0 1 12.76-12.776Zm0 2a10.774 10.774 0 1 1-10.76 10.774 10.767 10.767 0 0 1 10.76-10.772Z" fill="#fff" fill-rule="evenodd"/><path d="M29.469 33.084a6.6 6.6 0 1 1-6.6 6.6 6.6 6.6 0 0 1 6.6-6.6Z" fill="#fff" fill-rule="evenodd"/></g><g><path d="M99.285 47.981h-2.676L78.414 43.7h-3.746v1.07l-2.676 3.211h-9.1l2.676-5.887H63.43l-3.211 5.887h-4.281l2.676-7.492v-1.07l-2.676-7.492h4.281l3.211 5.887h2.14l-2.676-5.887h9.1l2.676 3.211v1.07h3.746l18.2-4.281h2.676l19.8 4.281V43.7Z" fill="#fff" fill-rule="evenodd"/></g><path fill="#49adc9" fill-rule="evenodd" d="M114 85h-3l-1 1-2 1H98a3.782 3.782 0 0 0-3-1h-3a4.414 4.414 0 0 0-1.949.538c.005 1.935-1.309 1.5-2.33 1.577A2.564 2.564 0 0 1 86 87l-4.963.279-1.253.418h-2.507l.835.835v.418h.836v-.418h2.924s-.034-.832 1.254-.832a1.811 1.811 0 0 1 1.674 1.25s.963 3.05 1.668 6.267-.836 2.924-.836 2.924c-1.5 0-1.671-.835-1.671-.835l-.835-6.684h-1.253V90.2h-2.925v-.414l-2.089.418-.836.418v2.088l-.836 1.253h-6.265l-3.342 6.267h-.836l-2.507-1.253L66 93.128v-1.671l.418-.835h-1.256l-.836-.422-1.253 2.51h-3.76l-.413-.835h-2.094v-.418h-2.924v.418h-2.507v-.418l-.418-.418h-.417l-.418.418H49.7v10.026h-1.667l-2.507-12.115 11.28-.418v-.418H49.7v-.417h.418V87.7h-.832v.835H35.5s-1.147-2.089-2.507-2.089a3.989 3.989 0 0 0-2.507 1.254h-3.342A58.111 58.111 0 0 1 16.7 86.444a7.269 7.269 0 0 0-2.924 0 3.793 3.793 0 0 1-2.089 1.671H8.762s-1.671-.981-1.671-5.431 1.671-4.6 1.671-4.6h2.507a2.476 2.476 0 0 1 2.507 1.671h2.089c5.32-1.636 15.04-1.253 15.04-1.253a1.138 1.138 0 0 0 .836.836h2.089c.842 0 1.671-1.671 1.671-1.671h2.089v.418h2.924v-.415h1.671v.418h3.342v-.418h2.089v.418h2.924v-.418h.418v-.417h11.28v.417h.835v.418h5.013v-.418h7.52l.418-.418h1.671l.418.836 3.342.418 2.507.418L86 79c.645-2.192 2-2 2-2s1.574-.045 2.293 2.579A4.185 4.185 0 0 0 92 80h3a3.782 3.782 0 0 0 3-1h10l2 1 1 1h3l5 2Z" /></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126"><g><path fill="#49adc9" fill-rule="evenodd" d="M106 94v-1H76v3h-3v-1h-2v11h2v2h-6v-2h2V96l-2-2h-2l-1 1H54l-1 1h-3v5h-2v4h-8.947L39 104h-1v-5l-2-1a3.229 3.229 0 0 1-2 1 11.073 11.073 0 0 1-3-1l-3 3v4h-4l-1-3 4-4v-2l-1-2h-8l-1 2v1l-1 2h-5l-4 3H4V90l3-2h20l1-1h6v-2h-5v-4h20v3l-2 1h-3v2h6l1 1h1v-2h9l2 2h11l2 2h30v-1h15v5h-15Zm-91-1H7v5h3l5-4v-1Zm19 2c-1.1 0-2 .448-2 1a1.152 1.152 0 0 0 1 .861V97h2v-.139A1.152 1.152 0 0 0 36 96c0-.552-.9-1-2-1Z"/><path d="M60 17h4v50h-4z" fill="#fff"/><path d="M37 40h51v4H37z" fill="#fff"/><path fill="#fff" fill-rule="evenodd" d="M62 22a20 20 0 1 1-20 20 20 20 0 0 1 20-20Zm0 5a15 15 0 1 1-15 15 15 15 0 0 1 15-15Z"/></g></svg>

After

Width:  |  Height:  |  Size: 724 B

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path d="M29 93V82h68v11l-13 6-21-10-21 10Z"/>
<path d="M38 69h50v9H38zM58 60h10v5H58z"/>
<path fill="#679552" d="M121 121H5v-20l17-7 20 10 21-10 21 10 20-10 17 7.2V121Z"/>
</svg>

After

Width:  |  Height:  |  Size: 261 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126"><g><path d="M99.866 31A54.163 54.163 0 0 0 84.65 16H121v15H99.866Zm1.691 24v14H49.99v-5H64l5-5h15l13-10-13-10H69l-5-5H49.993V16h18.6s32.964-.032 32.964 39Zm-5.918 19v16h-37.2V74h37.2Zm6.761 20 10.99 16H39l10.99-16h52.41Z" style="fill-rule:evenodd;fill:#679552"/><circle cx="18" cy="24" r="9" fill="#fff"/><path fill="#fff" fill-rule="evenodd" d="M5 34v40h5v37h16V74h5V34H5Z"/><path fill="#fff" fill-rule="evenodd" d="M82 55H66l-4 5H39V38h23l4 5h16l8 6Z"/></g></svg>

After

Width:  |  Height:  |  Size: 527 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126"><g fill="#fff"><path d="M29 97V86h68v11l-13 6-21-10-21 10z" fill-rule="evenodd"/><path d="M38 73h50v9H38zm20-9h10v5H58z"/></g><g fill-rule="evenodd"><path d="M5 104.955 22 98l20 10 21-10 21 10 20-10 17 7.192V121H5v-16.045Z" fill="#679552"/><path d="m34.262 28.536 7.438-7.442h21.4l28.839 12.093V44.35H34.262V28.536zM63.1 17.372H41.7V9h21.4l.93 1.861h19.536v4.651H64.031zM38.914 52.723c-4.744 0-4.651-4.651-4.651-4.651h9.3s.094 4.651-4.649 4.651zm12.093 0c-4.744 0-4.651-4.651-4.651-4.651h9.3s.095 4.651-4.649 4.651zm12.093 0c-4.744 0-4.651-4.651-4.651-4.651h9.3s.095 4.651-4.649 4.651zm12.093 0c-4.744 0-4.651-4.651-4.651-4.651h9.3s.096 4.651-4.648 4.651zm12.094 0c-4.744 0-4.651-4.651-4.651-4.651h9.3s.095 4.651-4.649 4.651z" fill="#679552"/></g></svg>

After

Width:  |  Height:  |  Size: 816 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path d="m12 39 2 3 36-7 3 16 18-16 2 12 41-5v-3l-38 4-3-16-17 16-2-12Z"/>
<path fill="#49adc9" d="M120 80h-4l-3 3v4l-1 1h-2l-2-2h-7l-1 1h-1v-1h-2l-1 2h-1v-2h-2l-1 2h-1v-2h-2l-1 2h-1v-2h-6v11h-5V86h-8v2h-4l-13 20h-4l-9-5v-4l4-5v-4l-1-2h-6v-2H21L11 97H6l-1-1V75h6v-1h19v1h3v-1h5l6-7h4l1-1h7l1 1h6l3 3v3h6l1 1h37l1-1h1l2 3h7v3Zm-76 24 1 1h4l6-8v-2h-7l-4 6v3Zm6-35h-4l-4 3v1h6l2-3v-1Zm2 21v3h5v-3h-5Zm14-16-4-5h-6v2h4l4 4h2v-1Z"/>
</svg>

After

Width:  |  Height:  |  Size: 514 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#49adc9" d="M27 82v-7h19v7h49v2h7v-2h2s3 1.3 3 3h10v-1h4v6h-4v-1h-10s-1 3-3 3h-2v-2h-7v2h-6l-2 2h-9s.2 1.6-2 4h-2v-4H60v3h-2s-3 4.5-3 9a7.3 7.3 0 0 1-5-3s.6-4.2 3-6v-3h-7a19 19 0 0 1-12 9s1.2-10.4-10-11c-5.4-.3-8 5-8 5h-2v-1H6v-6s-2 .3-2-3a6.2 6.2 0 0 1 3-5h20Z"/>
<path d="M34 33h36L48 55H34V33Zm42 0L54 55h33s11-.6 11-11-11-11-11-11H76Z"/>
</svg>

After

Width:  |  Height:  |  Size: 438 B

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M90 33s-6-8.3-18-15h43v15H90Zm2 24v14H51.5a9 9 0 0 0-6-6.1c3.1-1.2 6.5-3.7 6.5-8.8a9 9 0 0 0-6.5-9.2c3.1-1.2 6.5-3.7 6.5-8.8C52 27.5 40 28 40 28h-9V18h22s39 0 39 39ZM51.8 76H85v16H41v-8c2.6-.3 9.6-1.6 10.8-8ZM93 96l13 16H18l13-16h62Z"/>
<path d="M9 67h21L16 81H9V67Zm26 0L22 81h20s7-1.3 7-7-6-7-6-7h-8Z"/>
<path d="M9 49h21L16 63H9V49Zm26 0L22 63h20s7-1.3 7-7-6-7-6-7h-8Z"/>
<path d="M9 31h21L16 45H9V31Zm26 0L22 45h20s7-1.3 7-7-6-7-6-7h-8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 554 B

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#49adc9">
<path d="M79 41h9v10h-9z"/>
<path d="M75 41H64l-10-9v14l11 4v48h39l9-9V32l-10 9H92v14H75V41Z"/>
<path d="m54 27 11 10h37l11-10V16H54v11Z"/>
</g>
<path d="M8 99s24 16 26 16 26-16 26-16V53s-22-6-26-6-26 6-26 6v46Zm34-37a3.5 3.5 0 0 1 2-1h2s2 0 2 1v2a3.6 3.6 0 0 1-2 1h-2s-2 0-2-1v-2Zm0 6h6v21s-1 4-3 4-3-4-3-4V68Zm-11-6a3.5 3.5 0 0 1 2-1h2s2 0 2 1v2a3.6 3.6 0 0 1-2 1h-2s-2 0-2-1v-2Zm0 6h6v21s-1 4-3 4-3-4-3-4V68Zm-11-6a3.5 3.5 0 0 1 2-1h2s2 0 2 1v2a3.6 3.6 0 0 1-2 1h-2s-2 0-2-1v-2Zm0 6h6v21s-1 4-3 4-3-4-3-4V68Z"/>
</svg>

After

Width:  |  Height:  |  Size: 631 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126">
<path d="M24 26h15L24 13v13zm0 27h15L24 66V53zm73-4H24v-7h40v-5H24v-7h73s9 1.032 9 10-9 9-9 9z" fill="#fff"
fill-rule="evenodd" />
<path
d="M113 87v7l-6 4h-4l-2 1h-4v7s-2.794 2.22-5 0v-7h-2s.362 2.993-2 3h-3s-6.757 6.1-5 10a.828.828 0 0 1 0 1 1.664 1.664 0 0 1-1 0c-.724-.391-3.782-2.2-4-4h-9l-2 1h-4v4s.434 3-5 3a4.343 4.343 0 0 1-4-3 27.593 27.593 0 0 0 0-7 7.192 7.192 0 0 0-6-6h-8s-2-.3-2-2 1-2 1-2v-1H14V77h34l6-2h37l1 2h18l2 2h1v6h-1v2h1zm-35 13H68v7h6l4-5v-2zm8-1c-.149.459 0 1.984 1 2 .5.008 1.623.432 2-1a1.224 1.224 0 0 0 0-1c-.449-.726-2.39-1.886-3 0z"
fill-rule="evenodd" fill="#49adc9" />
</svg>

After

Width:  |  Height:  |  Size: 687 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126"><path d="M104 98H67V51l-13-3V32l9 9h12v14h17V41h12l9-9v57ZM79 51V41h9v10h-9ZM65 37 54 27V16h59v11l-11 10H65Z" fill="#49adc9" fill-rule="evenodd"/><path d="M37 112 11 96V54l26-6 26 6v42Zm-4-13 12-17h-8l3-12-12 16h9Zm21-38-3 3s-3.472-5-14-5-14 5-14 5l-3-3v9h8l-2-3c3.992-4.229 11-4 11-4s7.008-.229 11 4l-2 3h8v-9Z" fill="#fff" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 414 B

+9
View File
@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#de7b6c">
<path d="m9 47 29-8 9-29 7 7v38H16Z"/>
<path d="M82 25v4l-8.4-7.4L78 10l17 10v17.2Zm-7 37 8 1 12 12v8l17 17 1 14-15-2-16-17h-6.3L63 83v-8L50 63.4l9-3.4 3.9-10.1ZM19 95 9 79l12.9-4.9L30 83h-4l11.3 12H19Z"/>
</g>
<path d="M50 69v17H33l8 8h8l11 12h11V96L59 85v-8Z"/>
<path d="m43 80-6-6h-9l5 6h10ZM38 63v9l6 6V68ZM63 38l6 7h9l-6-7h-9ZM74 37l6 6V33l-6-5v9Z"/>
<path d="M69 50h17V34l8 8v7l12 12v10H96L85 59h-8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 526 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#de7b6c">
<path d="m44 20 3-10 7 7v13ZM31 55H16l-7-8 11.5-3.2Z"/>
<path d="M98 112 82 95H19L9 79l33.3-12.7L63 87h24V63L65.9 41.9 78 10l17 10v63l17 17 1 14Z"/>
</g>
<path d="M46 55v10l19 18h18V64L65 46H54V35L42 24l-3 14-14 5 11 12h10Z"/>
</svg>

After

Width:  |  Height:  |  Size: 340 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#de7b6c">
<path d="m9 47 29-8 9-29 7 7v38H16Z"/>
<path d="m113 114-15-2-16-17H19L9 79l50-19 19-50 17 10v63l17 17ZM34 83l-2 6 4 5 3 1h31l-9-10h-7v-6l-4-5h-8v9h-8Zm61-47-4-4h-8v9h-7l-2 6 6 6h6v5l9 11V36Z"/>
</g>
<path d="M36 86h9v-9h3l3 3v8h8l7 8v11H54l-7-8v-7h-8l-3-3v-3ZM86 44v-9h4l3 4v7h7l8 8v12H96l-7-9v-7h-8l-3-3v-3h8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 428 B

+9
View File
@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126">
<path fill="#de7b6c" fill-rule="evenodd" d="m9 47 29-8 9-29 7 7v38H16zm89 65L82 95h-9.026a10.5 10.5 0 0 0-10.482-10l-.288.014c-.069 0-.136-.01-.2-.01a9.959 9.959 0 0 0-8 4c-1.972-2.686-5.412-4-9-4a9.283 9.283 0 0 0-3.943.448 10.012 10.012 0 0 0-5.293 3.922A10.979 10.979 0 0 0 26.994 85l-.622.031L26 85a10 10 0 0 0-9.295 6.328L9 79l50-19 19-50 11.3 6.645A10.989 10.989 0 0 0 87.281 36.4a10.484 10.484 0 0 0-.78 17.73A10.99 10.99 0 0 0 95 73.819V83l17 17 1 14z"/>
<g fill="#fff">
<path fill-rule="evenodd" d="M26.493 88.014A7.493 7.493 0 1 1 19 95.507a7.493 7.493 0 0 1 7.493-7.493zm18.01 0a7.493 7.493 0 1 1-7.493 7.493 7.493 7.493 0 0 1 7.49-7.493zm18 0a7.493 7.493 0 1 1-7.508 7.493 7.5 7.5 0 0 1 7.505-7.493z"/>
<circle cx="92.5" cy="63.5" r="7.5"/>
<circle cx="92.5" cy="45.5" r="7.5"/>
<circle cx="92.5" cy="27.5" r="7.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 957 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#de7b6c">
<path d="m9 47 29-8 9-29 7 7v38H16Z"/>
<path d="M98 112 82 95H63.3l.7-19-13-8H38l21-8 7.4-19.6L69 43v11l9 9h17v20l17 17 1 14Zm-7-84H71.2L78 10l17 10v10.3ZM9 79l12.2-4.6L29 83v12H19Z"/>
</g>
<path d="M24 72h18l3 4v-4l5 1 9 4v18l-5-4v-6h-6l-2-2h-3v11h8l4 6H40l-7-7V81ZM65 31l17 1 3 4 1-4h4l9 5v18l-5-5v-5h-6l-1-2h-4v11h8l5 5H80l-6-6-1-12Z"/>
</svg>

After

Width:  |  Height:  |  Size: 453 B

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#c9b269" d="m9 47 29-8 9-29 7 7v38H16Z"/>
<path fill="#c9b269" d="M89.3 49.1a31 31 0 0 0-27 2.2L78 10l17 10v20.5ZM19 95 9 79l41.8-15.9A31 31 0 0 0 52.1 95H19Zm86-2 7 7 1 14-15-2-6-6.4a31.1 31.1 0 0 0 13-12.5Z"/>
<path d="M99 77h6s-.5 28-27 28c-26 0-27-27-27-27s-1-26.8 27-27c0 0 7.6-.6 13 3l5-7 9 20H84l4-7s-15.2-9-26 5-1 27.6 6 31 26.5 8.5 31-19Z"/>
<path fill="#c9b269" d="m76 70 17.3.7a17 17 0 1 1-10.8-9Z"/>
</svg>

After

Width:  |  Height:  |  Size: 510 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#de7b6c">
<path d="M51 32s-7.3-1.5-11.7 3L47 10l7 7v6.5c-1.9 1.6-3.2 4.2-3 8.5ZM36 45s-9.1-.2-12.6 10H16l-7-8 27.7-7.6A18 18 0 0 0 36 45Z"/>
<path d="M86 32s1.4-11.6-12-11h-.2L78 10l17 10v13a19 19 0 0 0-9-1ZM36 72s-2.2 14.3 15 13a10.5 10.5 0 0 0 4.7 10H19L9 79l22-8.4a47.4 47.4 0 0 0 5 1.4Zm50 13a46.6 46.6 0 0 0 10.5-.5L112 100l1 14-15-2-16-17h-1.5A11.9 11.9 0 0 0 86 85Z"/>
</g>
<path d="M100.8 68H90.6a6.2 6.2 0 0 1 6.2 6.6 6 6 0 0 1-6.2 6.3H76.4a5.2 5.2 0 0 1 5 5.6 5 5 0 0 1-5 5.4h-8.2v.1H60a5 5 0 0 1-5-5.4 5.1 5.1 0 0 1 5-5.6H46s-6 .2-6-6.4 6-6.6 6-6.6H36s-9-.1-9-9.4 9-9.6 9-9.6h10a6 6 0 0 1-6-6.4 6.4 6.4 0 0 1 6-6.6h13.2a4.5 4.5 0 0 0 .8 0h-.8c-1.5-.1-4.2-1-4.2-5.4 0-6 5-5.6 5-5.6h16.4s5-.5 5 5.6c0 4.5-2.7 5.3-4.2 5.4h-.8a4.7 4.7 0 0 0 .8 0h13.4s6.2.3 6.2 6.6-6.2 6.4-6.2 6.4h10.2s9.2.3 9.2 9.6-9.2 9.4-9.2 9.4Z"/>
</svg>

After

Width:  |  Height:  |  Size: 930 B

+14
View File
@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#de7b6c">
<path d="m9 47 29-8 9-29 7 7v38H16Z"/>
<path d="M75.8 15.7 78 10l17 10v14.5Zm-9.6 25.5L95 70v13l17 17 1 14-15-2-16-17H71L42.3 66.3 59 60ZM9 79l7.2-2.8L35 95H19Z"/>
</g>
<path d="m14 69 5-5 15 15-5 5Z"/>
<path d="m30 85 5-5 15 15-5 5Z"/>
<path d="m33 73 5-5 15 15-5 5Z"/>
<path d="m49 89 5-5 15 15-5 5Z"/>
<path d="m64 19 5-5 15 15-5 5Z"/>
<path d="m80 35 5-5 15 15-5 5Z"/>
<path d="m68 38 5-5 15 15-5 5Z"/>
<path d="m84 54 5-5 15 15-5 5Z"/>
</svg>

After

Width:  |  Height:  |  Size: 568 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill-rule="evenodd"><path d="M81 103v4l6 6 1 1H65l1-1 6-6v-8l6-7V78h9v18zm-7-16-6 7H58l-6-7V74H39V58l4-4h8l5-4h14l5 4h8l4 4v16H74v13zm-4-29H56v12h14V58zM48 92l6 7v8l6 6 1 1H38l1-1 6-6v-4l-6-7V78h9v14zm11-16a2 2 0 1 1-2 2 2 2 0 0 1 2-2zm8 0a2 2 0 1 1-2 2 2 2 0 0 1 2-2zm-8 7a2 2 0 1 1-2 2 2 2 0 0 1 2-2zm8 0a2 2 0 1 1-2 2 2 2 0 0 1 2-2z" fill="#49adc9"/><path d="M31 37H18l9-9h4s5 .116 5 4.5-5 4.5-5 4.5zm-16 0H8v-9h16zm16-13H17l9-9h5s5 .116 5 4.5-5 4.5-5 4.5zm-17 0H8v-9h15zm99 13h-13l9-9h4s5 .116 5 4.5-5 4.5-5 4.5zm-16 0h-7v-9h16zm16-13H99l9-9h5s5 .116 5 4.5-5 4.5-5 4.5zm-17 0h-6v-9h15z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 672 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M90 33s-6-8.3-18-15h43v15H90Zm2 24v14H44s9-22.4 9-28-9-25-9-25h9s39 0 39 39Zm-7 35H50v-8l-6-6v-2h41v16Zm-47 9h12v-5h43l13 16H18l9-11h11Z"/>
<path d="m17 50 5-20L2 56l14-1-4 20 20-26Z"/>
<path d="M40 69v11l6 6v11H27V86l6-6V69s-2-4.3-4-9.5L38 46H24.5l-.3-1.1 1.8-10c2.7-7.5 7-16.9 7-16.9h7s9 19.4 9 25-9 26-9 26Z"/>
</svg>

After

Width:  |  Height:  |  Size: 423 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#49adc9" d="M4 95v-9l6-5v-5h14l3-3h2v5h6l3 1 1 2h23l4-3h29v2l4 1 1 3h19l2 2v17l-2 2H97v1h-5v-1H68v1h-2v-1H53v1H27v-1H6l-2-2v-8Z"/>
<path d="M80 52c-8.3 0-28-7-28-7h-7l-4 7H26l4-9h-5l-3 9h-8l5-12v-1l-5-12h8l3 9h5l-4-9h15l4 7h7s19.7-7 28-7 32 7 32 7v11s-23.7 7-32 7Z"/>
</svg>

After

Width:  |  Height:  |  Size: 364 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path d="M62 65v-9l-3-4 6-10 1 2 1 3 5 5-4 5v8l15-14s0-6.1-5-18a52.4 52.4 0 0 0-5 7V28L60 15l-2 16-9 9v14Z"/>
<path fill="#49adc9" d="M81 92v1h3v4l-4 4h-4v3l-12 9h-7l-5-7v-6l-7-10H29l-4 5H9l-5-4v-8h18l2-2h18v-2h8v2h4v-2h20v2h9v2h30l2 1h3v2h-1l-2 1v3h3v-3l2 1h1v4H81Zm-58-5h-7l-1 2h-1l-1-2h-3v6h11l2-2v-4Zm43 5-4-4H50v3l7 8h2l7-4v-3Zm46-4H81v2h31v-2Z"/>
</svg>

After

Width:  |  Height:  |  Size: 437 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M90 33s-6-8.3-18-15h43v15H90Zm2 24v14H51.5l-.5-1-1-1h-4l-1-1h-9v-2h9l1-1h4l1-1 1-2 1-1v-1l-1-1-1-2-1-1h-4l-1-1h-9v-3h9l1-1h4l1-1 1-2 1-1v-1l-1-1-1-2-1-1h-4l-1-1h-9v-2h9l1-1h4l1-1 1-2 1-1v-1l-1-1-1-2-1-1h-4l-1-1h-9v-1h-5v-9h22s39 0 39 39ZM52 85l-1-2-1-1h-4l-1-1h-4v-2h4l1-1h4l1-1 .5-1H85v16H45l1-1h4l1-1 1-2 1-1v-1Zm41 11 13 16H18l13-16h62Z"/>
<path d="M9 90h26l1-1h8l1-1h3l1-1v-1l-1-1h-3l-1-1h-8l-1-1H9v7Z"/>
<path d="M9 77h26l1-1h8l1-1h3l1-1v-1l-1-1h-3l-1-1h-8l-1-1H9v7Z"/>
<path d="M9 64h26l1-1h8l1-1h3l1-1v-1l-1-1h-3l-1-1h-8l-1-1H9v7Z"/>
<path d="M9 50h26l1-1h8l1-1h3l1-1v-1l-1-1h-3l-1-1h-8l-1-1H9v7Z"/>
<path d="M9 37h26l1-1h8l1-1h3l1-1v-1l-1-1h-3l-1-1h-8l-1-1H9v7Z"/>
</svg>

After

Width:  |  Height:  |  Size: 785 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126"><g fill-rule="evenodd"><path fill="#fff" d="M27 28h10v3h21v23H37v3H27V28Zm37 3v23h25s11 .049 11-11v-1s.82-11-11-11H64Z"/><path fill="#49adc9" d="M25 77v-2h9l1-3h6v1h4v-1h2v2h3v-2h4v2h35v-2h7v1h3v-1h7l2 2h3l1 1h5v4h-2v5l2 2h4v5h-3l-2 2h-8l-1 1h-6s2.064.25 2 3c-.031 1.32-2 3-2 3h-6v2h6s2 1.724 2 3a9.009 9.009 0 0 1 0 1 3.778 3.778 0 0 1-2 3h-5s.262 1.02-1 1a2.582 2.582 0 0 1-1-1h-6V94h-3l-1-1H72v7l-2 2h-3l-1 1H55l-6 11h-6l-2-2v-3l8-10v-3l-2-2H37l-5-3v-3h-7v-2H15v17l-3 2H7l-2-2V74l2-2h5l3 2v3h10Zm36.5 20c1.933 0 3.5.9 3.5 2s-1.567 2-3.5 2-3.5-.895-3.5-2 1.567-2 3.5-2Z"/></g></svg>

After

Width:  |  Height:  |  Size: 646 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#49adc9">
<path d="M79 41h9v10h-9z"/>
<path d="M75 41H63l-9-9v12l13 19v35h37l9-9V32l-9 9H92v14H75V41Z"/>
<path d="m54 27 11 10h37l11-10V16H54v11Z"/>
</g>
<path fill-rule="evenodd" d="M20 114 9 98V65l11-16v8h7l4-14h10l4 14h7v-8l11 16v33l-11 16v-8h-7l-4 14H31l-4-14h-7v8Zm1-50h13a1 1 0 0 0 1 1h12s5 2 5 3-5 3-5 3H35a1 1 0 0 0-1 1H21v-8Zm0 13h13a1 1 0 0 0 1 1h12s5 2 5 3-5 3-5 3H35a1 1 0 0 0-1 1H21v-8Zm0 13h13a1 1 0 0 0 1 1h12s5 2 5 3-5 3-5 3H35a1 1 0 0 0-1 1H21v-8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 565 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#49adc9">
<path d="M79 41h9v10h-9z"/>
<path d="M75 41H63l-9-9v12l13 19v35h37l9-9V32l-9 9H92v14H75V41Z"/>
<path d="m54 27 11 10h37l11-10V16H54v11Z"/>
</g>
<path fill-rule="evenodd" d="M20 114 9 98V65l11-16v8h7l4-14h10l4 14h7v-8l11 16v33l-11 16v-8h-7l-4 14H31l-4-14h-7v8Zm27-30ZM36 74a8 8 0 1 1-7.7 6 8 8 0 0 1 7.7-6ZM9 80h19v4H9v-4Zm25-8v-8h4v8h-4Zm20 12h-8v-4h8v4Zm-20 16v-8h4v8h-4ZM21 70l3-3 6 6-3 3Zm27-3 3 3-6 6-3-3ZM21 94l3 3 6-6-3-3Zm27 3 3-3-6-6-3 3Z"/>
</svg>

After

Width:  |  Height:  |  Size: 566 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126">
<path d="m92 29-3 1.25-2 .917h-8L76 33H42V22h34l3 1.833h8l2 .917L92 26l2 1.5zm-59 3.083V22h5v11h-5v-.917zM92 44l-3 1.25-2 .917h-8L76 48H42V37h34l3 1.833h8l2 .917L92 41l2 1.5zm-59 3.083V37h5v11h-5v-.917zM92 59l-3 1.25-2 .917h-8L76 63H42V52h34l3 1.833h8l2 .917L92 56l2 1.5zm-59 3.083V52h5v11h-5v-.917z" fill="#fff" fill-rule="evenodd"/>
<path d="M14 81h19l2-2h14l1-1h16l1 2h17l2 4h4v-1h5l1 1 18 1 1-1h6l1 1v2l-1 1h-6l-1-1H95v1h1v3h-6l3 18 2 2v2l-7-2v-2h2v-2l-3-1-2-1v-1h2l-1-13h-2l-2 1v3l-9 10h-4l-1 1h-2l-1 2H53l-2-1-2-1V91h2v-2h-2v1l-1 1v2a1.824 1.824 0 0 1-1 1 3.907 3.907 0 0 1-2 0l-1-1h-1v1l-4 7-7-1-4-1-5-4-1-1h-3v1h-2v-1h-6l-2-2-1-11h6zm-2 6a4.372 4.372 0 0 1 3 0c.461.42 0 2 0 2a1.128 1.128 0 0 0-1 0c-.164.307.213 1.052-1 1a1.046 1.046 0 0 1-1-1s-.287-1.713 0-2zm17 4a.911.911 0 0 1 1.046-1A.836.836 0 0 1 31 91h1a2.477 2.477 0 0 1 0 2 5.093 5.093 0 0 1-1 1v2a5.82 5.82 0 0 1-1 0 9.229 9.229 0 0 1-2-1 12.655 12.655 0 0 1 0-3 1.875 1.875 0 0 1 1-1zm6 8v-3l1-2s3.368 1.283 5 1c.059-.01-1 1-1 1l-2 3h-3zm15-19h6v1a4.969 4.969 0 0 0-2 0 1.707 1.707 0 0 0-1 1h-3v-2zm17 2v-1h2l1 1v2a6.4 6.4 0 0 1-1 0c-.209-1.408-2-2-2-2zm5-1v1h3l1 1h1v-1h-1v-1h-4zm7 0v1h1v1h1v-1zm-2 0v1h1v1h1v-1zm14 7h-2v-1a4.273 4.273 0 0 0 2 0v1zm-25 2h2s1.087.085 1 2c-.011.248-.147.687 1 1a10.438 10.438 0 0 0 2 0v1h-3a1.039 1.039 0 0 1-1-1v-2h-2v-1zm7 0s-1.256.489-1 1c.02.041 2 0 2 0s.306-.429-1-1zm8-9v1h1v1h1v-1zm-21-1v1h-4v1h6v-2h-2zM38 93s-.58.879 3 1c0 0 .5-2.037-1-2s-2-.248-2 1zm8-2a.563.563 0 0 0 0 1s.686.51 1 0a.961.961 0 0 0 0-1c-.186-.73-.224-.479-1 0z" fill-rule="evenodd" fill="#49adc9"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path d="M63 109H34L21 95l15 2-2-12 11 11V76l14 13s2.5-21.5 3-30c.4-6.6-4-14-4-14l-11 1c-2.3.2-9.1-1-9-9s8-6 8-6 1.2-7 11-5c0 0-.9-5 6-5v88Zm0 0h29l13-14-15 2 2-12-11 11V76L67 89s-2.5-21.5-3-30c-.4-6.6 4-14 4-14l12 1c2.3.2 8.1-1 8-9s-8-6-8-6-1.2-7-11-5c0 0 .9-5-6-5v88Z"/>
<path fill-rule="evenodd" d="M63 53c16.6 0 30 3.6 30 8s-13.4 8-30 8-30-3.6-30-8 13.4-8 30-8Zm0 4c12.2 0 22 1.8 22 4s-9.8 4-22 4-22-1.8-22-4 9.9-4 22-4Z"/>
<path fill="#c9b269" d="M4 122v-20l20 20H4Zm118 0v-20l-20 20h20Zm0-118v20L102 4h20ZM4 4v20L24 4H4Z"/>
</svg>

After

Width:  |  Height:  |  Size: 615 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126">
<path fill="#679552" fill-rule="evenodd" d="M99.866,31A54.163,54.163,0,0,0,84.65,16H121V31H99.866Zm1.691,24V69H49.99V63H68l2-2,8-1,6-4,3-4-3-4-5-4V42l5-4,3-4-3-4-6-4-8-1-2-2H49.99V16h18.6S101.557,15.968,101.557,55ZM95.639,74V90h-37.2V74h37.2ZM102.4,94l10.99,16H39L49.99,94H102.4Z"/>
<path fill="#fff" fill-rule="evenodd" d="M39,28V40H66.25l1.125-1.714h9L77.5,36.571h3.375L83,34l-2.125-2.571H77.5l-1.125-1.714h-9L66.25,28H39Z"/>
<path fill="#fff" fill-rule="evenodd" d="M39,46V58H66.25l1.125-1.714h9L77.5,54.571h3.375L83,52l-2.125-2.571H77.5l-1.125-1.714h-9L66.25,46H39Z"/>
<circle fill="#fff" cx="18" cy="24" r="9"/>
<path fill="#fff" fill-rule="evenodd" d="M5,34V74h5v37H26V74h5V34H5Z"/>
</svg>

After

Width:  |  Height:  |  Size: 774 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M121 121H5v-20l17-7 20 10 21-10 21 10 20-10 17 7.2V121Z"/>
<path d="M29 93V82h68v11l-13 6-21-10-21 10Z"/>
<path d="M58 78 46 66V54l9-8 4-15 10 14v7l4-4 10 12-18 18v-8l4-4-6-3v-8l-7 10 3 4v9h-1ZM52 78H38v-9h5Zm28-9h8v9H71Z"/>
</svg>

After

Width:  |  Height:  |  Size: 337 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#49adc9" d="M118 95h-17v2h-4v6l-5 5h-5l-1 6v1h-6l-8-3-1-2 4-5v-3H64l-2-2v-3h-3l-2 3v6h-1v6h-7v-6l-7-8h-5v-4h-3v2h-7v-2H14l-2 3H8v-3H5V79h3v-3h4l2 3h13v-3h7v3h5V68h3v4h22v4h2v-7h3v9h6l4 3h23v-1h4v-3h2v3h2v-3h2v3h2v-3h2v3h3v-2h2v15Zm-64 5h-1v5h1v-5Zm0 6h-1v5h1v-5Zm24 2v4h6v-7h-3Zm11-7h-5v3h5v-3Z"/>
<path d="M94 38v-4h10v4H94Zm-5-12.8 7.1-7.1 2.8 2.8-7 7.1ZM81 46a10 10 0 0 1-9.5-7H23v-6h48.5A10 10 0 1 1 81 46Zm-2-33h4v10h-4V13Zm-16 7.9 2.9-3 7.1 7.2-2.9 3Zm10 26L66 54 63 51.1l7.2-7.1ZM83 59h-4V49h4v10Zm16-8L96.2 54l-7.1-7 2.8-2.9Z"/>
</svg>

After

Width:  |  Height:  |  Size: 635 B

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#49adc9" d="M31 83V59L18 83h13Z"/>
<path d="m35 87 2 25h5V87h-7ZM45 87v25h5l2-25h-7ZM76 87l2 25h5V87h-7ZM86 87v25h5l2-25h-7ZM35 83V33h17v50H35Z"/>
<path d="M76 33h17v50H76z"/>
<path fill="#49adc9" d="M97 83h13L97 59v24ZM56 83V29H35V16h58v13H72v54H56Z"/>
</svg>

After

Width:  |  Height:  |  Size: 352 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill-rule="evenodd">
<path d="M121 85v3H67v6h-3v16H53V93h-8a50.6 50.6 0 0 0-1 9s-2.038 2.452-7-1c0 0-.913-2.905 3-8v-3l-2-2H16v2h1v2l-1 1h-3l-3-3H8l-1 3H4V78h8l2 3h5l1-1h7l4-2h16v-1h18v1h4v2h52v2h-2v3h2Zm-69 4h-6v3h6v-3Z" fill="#49adc9"/>
<path d="m92 29-3 1.25-2 .917h-8L76 33H42V22h34l3 1.833h8l2 .917L92 26l2 1.5zm-59 3.083V22h5v11h-5v-.917zM92 44l-3 1.25-2 .917h-8L76 48H42V37h34l3 1.833h8l2 .917L92 41l2 1.5zm-59 3.083V37h5v11h-5v-.917zM92 59l-3 1.25-2 .917h-8L76 63H42V52h34l3 1.833h8l2 .917L92 56l2 1.5zm-59 3.083V52h5v11h-5v-.917z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 633 B

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M90 33s-6-8.3-18-15h43v15H90Zm2 24v14H31v-3h7l1-1 7-1 1-1h3l3-4v-1l-3.1-4H47l-1-1-7-1h-5v-1h5l7-1 1-1h3l3-4v-1l-3-4h-3l-1-1-6-1h-6l12-1 1-1h3l3-4v-1l-3-4h-3l-1-1-10-1h-5v-9h22s39 0 39 39Zm-7 19v16H41V76h44Zm8 20 13 16H18l13-16h62Z"/>
<path d="M9 57v7h26l1-1h8l1-1h3l1-1.5-1-1.5h-3l-1-1h-8l-1-1H9Z"/>
<path d="M9 43v7h26l1-1h8l1-1h3l1-1.5-1-1.5h-3l-1-1h-8l-1-1H9Z"/>
<path d="M9 30v7h26l1-1h8l1-1h3l1-1.5-1-1.5h-3l-1-1h-8l-1-1H9Z"/>
</svg>

After

Width:  |  Height:  |  Size: 542 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M90 33s-6-8.3-18-15h43v15H90Zm2 24v14H44s9-22.4 9-28-9-25-9-25h9s39 0 39 39Zm-7 35H50v-8l-6-6v-2h41v16Zm-47 9h12v-5h43l13 16H18l9-11h11Z"/>
<path d="M40 69v11l6 6v11H36V18h4s9 19.4 9 25-9 26-9 26Z"/>
<path d="M33 69v11l-6 6v11h10V18h-4s-9 19.4-9 25 9 26 9 26Z"/>
</svg>

After

Width:  |  Height:  |  Size: 372 B

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M99 120a91 91 0 0 0-4.5-27h15.3a53.7 53.7 0 0 1 7.2 27H99Zm-8-35c2.5-.2 4.7-3.3 6.2-6.8A54 54 0 0 1 107.9 90H93.4L91 85Zm-7.9-11a37.2 37.2 0 0 0-9-6.8 53.7 53.7 0 0 1 8.8 2.6c0 1.4 0 2.8.2 4.1Zm1.9 6.5a8.8 8.8 0 0 0 2.2 3.4 50.1 50.1 0 0 1 3.1 6.1H65v-5.2l1-.8c2.4-1.9 4.7-6.3 4.7-6.3s.3-4 .5-8.5A35 35 0 0 1 85 80.5ZM35.5 93H62v27H31a85.5 85.5 0 0 1 4.5-27ZM56 69v8s3.4 5.2 5 7a8.6 8.6 0 0 0 1 1v5H36.7A38.3 38.3 0 0 1 56 69Zm-11.1.2a53.8 53.8 0 0 1 8.5-2.3 37 37 0 0 0-9.5 7 30.5 30.5 0 0 0 1-4.7ZM18 90a54 54 0 0 1 11.6-12.5C31 81.1 33 84.9 36 85l-2.3 5H18.1Zm10 30H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27ZM65 93h26.5a85.5 85.5 0 0 1 4.6 27H65V93Zm-2 81a53.7 53.7 0 0 1-32.6-11h65.2A53.7 53.7 0 0 1 63 174Z"/>
<path d="m32 75 3 6s1.3 2.3 3 0a28.7 28.7 0 0 0 3-6V59s2-.5 2-2V37H30v20a1.9 1.9 0 0 0 2 2v16Zm-1-47a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H31Z"/>
<path d="m59 75 3 6s1.3 2.3 3 0a28.7 28.7 0 0 0 3-6V59s2-.5 2-2V37H57v20a1.9 1.9 0 0 0 2 2v16Zm-1-47a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H58Z"/>
<path d="m86 75 3 6s1.3 2.3 3 0a28.7 28.7 0 0 0 3-6V59s2-.5 2-2V37H84v20a1.9 1.9 0 0 0 2 2v16Zm-1-47a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H85Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M99 120a91 91 0 0 0-4.5-27h15.3a53.7 53.7 0 0 1 7.2 27H99Zm-3-31V77.3A54 54 0 0 1 107.9 90H95ZM77 72.6V89l1 1H65v-4.6l8-8.4v-7a33.6 33.6 0 0 1 4 2.6ZM35.5 93H62v27H31a85.5 85.5 0 0 1 4.5-27ZM54 70v7l8 8.4V90H36.7A39 39 0 0 1 54 70ZM18.1 90a54 54 0 0 1 17.6-16.5l4.7 4.5a51 51 0 0 0-6.8 12H18.1Zm10 30H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27Zm36.9 0V93h15.8l5.7 6 5.2-5.5A86 86 0 0 1 96 120H65Z"/>
<path d="m35 68 6.5 7 6.5-7V46s3-.8 3-3V26H32v17.1a3 3 0 0 0 3 2.9v22ZM33 17a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h17a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H33Z"/>
<path d="m57 76 6.5 7 6.5-7V54s3-.8 3-3V34H54v17.1a3 3 0 0 0 3 2.9v22Z"/>
<path d="M55 25a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h17a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H55Z"/>
<path d="m80 88 6.5 7 6.5-7V66s3-.8 3-3V46H77v17.1a3 3 0 0 0 3 2.9v22Z"/>
<path d="M78 37a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h17a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H78Z"/>
</svg>

After

Width:  |  Height:  |  Size: 992 B

+17
View File
@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M99 120a91 91 0 0 0-4.5-27h15.3a53.7 53.7 0 0 1 7.2 27H99ZM86.1 77.4l-3-7.5A54 54 0 0 1 107.9 90H93.4a50.6 50.6 0 0 0-7.2-12.6ZM90.3 90H69V68.3l1 .3L76 84l8.7-3.7a47 47 0 0 1 5.5 9.7Zm-48.1-9.7 8.7 3.7L57 68.6l.9-.3V90H36.7a47 47 0 0 1 5.5-9.7ZM33.6 90H18.1a54 54 0 0 1 26-20.5l-3.3 7.9A50.5 50.5 0 0 0 33.6 90Zm-5.5 30H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27ZM63 174a53.7 53.7 0 0 1-32.6-11h65.2A53.7 53.7 0 0 1 63 174Zm28.5-81a85.5 85.5 0 0 1 4.6 27H65V93h26.5Zm-56 0H62v27H31a85.5 85.5 0 0 1 4.5-27Z"/>
<path d="M62 49h3v4h-3z"/>
<path d="M62 58h3v4h-3z"/>
<path d="M62 67h3v4h-3z"/>
<path d="M62 76h3v4h-3z"/>
<path d="M62 85h3v4h-3z"/>
<path d="m56 47.8 2.8 1-1.2 3.8-2.9-1Z"/>
<path d="m53.2 56.4 2.8 1-1.2 3.7-2.8-.9Z"/>
<path d="m50.4 65 2.9.9-1.2 3.8-2.9-1Z"/>
<path d="m47.4 73 2.9.9-1.2 3.8-2.9-1Z"/>
<path d="m68.4 48.5 2.9-1 1.3 3.9-2.9 1Z"/>
<path d="m71.4 57 2.8-1 1.3 3.9-2.8 1Z"/>
<path d="m74.3 65.6 2.8-1 1.3 3.8-2.8 1Z"/>
<path d="m76.7 73.8 2.8-1 1.3 3.8-2.8 1Z"/>
<path d="M70.8 32.6 76 37l-6.3-.3L71 43l-5-4-2.5 6-2.5-6-5 4 1.3-6.3-6.3.3 5.2-4.4L51 29h6l-1-6 6 4V12h3v15l6-4-1 6h6Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M99 120a91 91 0 0 0-4.5-27h15.3a53.7 53.7 0 0 1 7.2 27H99ZM74.1 67.2A54 54 0 0 1 107.9 90H93.4c-5.3-13-13-19.5-19.2-22.8ZM33.6 90H18.1a54 54 0 0 1 35.3-23.1A42.4 42.4 0 0 0 33.6 90Zm-5.5 30H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27ZM63 174a53.7 53.7 0 0 1-32.6-11h65.2A53.7 53.7 0 0 1 63 174Zm33-54H65V93h26.5a85.5 85.5 0 0 1 4.6 27Zm-5.7-30H65v-3l7.6-17.1c8.7 4.4 14.3 12 17.7 20.1ZM62 120H31a85.5 85.5 0 0 1 4.5-27H62v27Zm0-53v23H36.7A37 37 0 0 1 62 67Z"/>
<path d="m65 79 16-42-16 5V12L49 55l16-5v29Z"/>
<path d="m33 65.7 3.2 5A52 52 0 0 0 27 77l-3.7-3.7a41.7 41.7 0 0 1 9.8-7.6ZM47 60.4l2 5.3a54.8 54.8 0 0 0-10.2 3.7l-3-5.1A51 51 0 0 1 47 60.4ZM61 58.9v5.2a54.2 54.2 0 0 0-9 .9l-1.6-5.3A63.9 63.9 0 0 1 61 59Zm18.3 2.2a60.2 60.2 0 0 1 10.9 3.6L87.6 69a51.2 51.2 0 0 0-10.1-3.4l1.2-3.6Zm23.4 12.2L99 77a31.8 31.8 0 0 0-8.8-6.7l3-4.2a35.4 35.4 0 0 1 9.5 7.2Z"/>
</svg>

After

Width:  |  Height:  |  Size: 988 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M99 120a91 91 0 0 0-4.5-27h15.3a53.7 53.7 0 0 1 7.2 27H99Zm-8.3-35.7L97 78a54 54 0 0 1 10.9 12H93.4a55.8 55.8 0 0 0-2.7-5.7ZM29 78l7 6.7a56 56 0 0 0-2.5 5.3H18.1a54 54 0 0 1 11-12Zm-1 42H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27ZM63 174a53.7 53.7 0 0 1-32.6-11h65.2A53.7 53.7 0 0 1 63 174Zm33-54H65V93h.1l8.9 8 8-8h9.5a85.5 85.5 0 0 1 4.6 27ZM35.6 93h9.2l8.3 8 8.9-8h.1v27H31a85.5 85.5 0 0 1 4.5-27Zm1.2-3 1.5-3.3 3.4 3.3h-5Zm52-3.6 1.6 3.6H85Z"/>
<path d="m75.7 79 3 3 7.2-7 5 5-17.2 17-5-5 7-7-3-3-5.1 4H59l-5-4-3 3 7 7-5 5-17-17 5-5 7 7 3-3-18-17V41h7c-.5-23 22-24 22-24h2.5S87.5 18 87 41H94v21Zm-4.2-2a2.5 2.5 0 1 0-2.5-2.5 2.5 2.5 0 0 0 2.5 2.5Zm0-9a2.5 2.5 0 1 0-2.5-2.5 2.5 2.5 0 0 0 2.5 2.5Zm-8 14a2.5 2.5 0 1 0-2.5-2.5 2.5 2.5 0 0 0 2.5 2.5Zm0-9a2.5 2.5 0 1 0-2.5-2.5 2.5 2.5 0 0 0 2.5 2.5Zm0-10a2.5 2.5 0 1 0-2.5-2.5 2.5 2.5 0 0 0 2.5 2.5Zm-8 14a2.5 2.5 0 1 0-2.5-2.5 2.5 2.5 0 0 0 2.5 2.5Zm0-9a2.5 2.5 0 1 0-2.5-2.5 2.5 2.5 0 0 0 2.5 2.5ZM82 41H45v14l8 6 9-7h2.6l9.2 7 8.2-6V41Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+13
View File
@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M99 120a91 91 0 0 0-4.5-27h15.3a53.7 53.7 0 0 1 7.2 27H99ZM79 70.3v-1.8A54 54 0 0 1 107.9 90H93.4c-4-9.8-9.4-15.9-14.4-19.7ZM57 90H36.7A42 42 0 0 1 48 74.1V84h9v6Zm-23.4 0H18.1A54 54 0 0 1 48 68.2v2A45 45 0 0 0 33.6 90Zm-5.5 30H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27ZM63 174a53.7 53.7 0 0 1-32.6-11h65.2A53.7 53.7 0 0 1 63 174Zm33-54H65V93h26.5a85.5 85.5 0 0 1 4.6 27ZM35.6 93H62v27H31a85.5 85.5 0 0 1 4.5-27Zm54.8-3H70v-6h9V74a42 42 0 0 1 11.3 16Z"/>
<path d="M53 24h3v15h-3z"/>
<path d="M53 44h3v15h-3z"/>
<path d="M53 64h3v15h-3z"/>
<path d="M62 15h3v13h-3z"/>
<path d="M62 31h3v15h-3z"/>
<path d="M62 51h3v16h-3z"/>
<path d="M62 71h3v16h-3z"/>
<path d="M71 24h3v15h-3z"/>
<path d="M71 44h3v15h-3z"/>
<path d="M71 64h3v15h-3z"/>
</svg>

After

Width:  |  Height:  |  Size: 863 B

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#c9b269" d="M4 122v-20l20 20H4Zm118 0v-20l-20 20h20Zm0-118v20L102 4h20ZM4 4v20L24 4H4Z"/>
<circle cx="63" cy="63" r="12"/>
<path d="m43.8 84.7-.7-.7-1.4-1.4-.7-.7 9.2-9.2.7.7 1.4 1.4.7.7Z"/>
<path d="m85 82.2-.7.7-1.4 1.4-.7.7-9.2-9.2.7-.7 1.4-1.4.7-.7Z"/>
<path d="m43.8 41.3-.7.7-1.4 1.4-.7.7 9.2 9.2.7-.7 1.4-1.4.7-.7Z"/>
<path d="m85 43.8-.7-.7-1.4-1.4-.7-.7-9.2 9.2.7.7 1.4 1.4.7.7Z"/>
<path d="M15 65v-4h32v4H15Z"/>
<path d="M79 61h32v3H79z"/>
<path d="M79 62h32v3H79z"/>
<path d="M61 79h3v21h-3z"/>
<path d="M62 79h3v21h-3z"/>
<path d="M61 26h3v21h-3z"/>
<path d="M62 26h3v21h-3z"/>
</svg>

After

Width:  |  Height:  |  Size: 697 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M99 120a91 91 0 0 0-4.5-27h15.3a53.7 53.7 0 0 1 7.2 27H99ZM78 69.6l.4-1.3A54 54 0 0 1 107.9 90H93.4A44.6 44.6 0 0 0 78 69.6Zm-29.8.5A45 45 0 0 0 33.6 90H18.1a54 54 0 0 1 29.5-21.7 16 16 0 0 0 .6 1.8ZM28.1 120H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27ZM63 174a53.7 53.7 0 0 1-32.6-11h65.2A53.7 53.7 0 0 1 63 174Zm33-54H65V93h26.5a85.5 85.5 0 0 1 4.6 27Zm-5.7-30H65V79.9a16 16 0 0 0 11.7-7.6c6.4 4.5 10.7 11 13.6 17.7ZM62 120H31a85.5 85.5 0 0 1 4.5-27H62v27ZM36.7 90a41 41 0 0 1 13-17.2A16 16 0 0 0 62 80v10H36.7Z"/>
<circle cx="63" cy="64" r="12"/>
<path d="M35 62h12v3H35zM79 62h12v3H79z"/>
<path d="m73.1 51.5 8.5-8.5 2.1 2.1-8.4 8.5Z"/>
<path d="M53 51.8 44.2 43 42 45.2l8.8 8.8Z"/>
<path d="M62 13h2v45h-2z"/>
</svg>

After

Width:  |  Height:  |  Size: 836 B

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M94.5 93h15.3a53.7 53.7 0 0 1 7.2 27H99c-.4-11-2-19.9-4.5-27ZM74.2 67.2A54 54 0 0 1 107.9 90H93.4c-5.3-13-13-19.5-19.2-22.8ZM90.3 90H65V67a37 37 0 0 1 25.3 23Zm-54.8 3H62v27H31a85.5 85.5 0 0 1 4.5-27ZM62 67v23H36.7A37 37 0 0 1 62 67ZM33.6 90H18.1a54 54 0 0 1 35.3-23.1A42.4 42.4 0 0 0 33.6 90Zm-5.5 30H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27Zm67.5 43a54 54 0 0 1-65.2 0h65.2Zm-4-70a85.5 85.5 0 0 1 4.5 27H65V93h26.5Z"/>
<path d="M54 39V11H29l18 28h7ZM73 11h25L80 39h-7V11Z"/>
<path d="M59 11h9v33h9L64 64 50 44h9"/>
</svg>

After

Width:  |  Height:  |  Size: 641 B

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M99 120a91 91 0 0 0-4.5-27h15.3a53.7 53.7 0 0 1 7.2 27H99ZM76 68.2v-.6A54 54 0 0 1 107.9 90H93.4A43.6 43.6 0 0 0 76 68.2Zm-25 0A43.5 43.5 0 0 0 33.6 90H18.1A54 54 0 0 1 51 67.4v.8ZM28 120H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27Zm35 54a53.7 53.7 0 0 1-32.6-11h65.2A53.7 53.7 0 0 1 63 174Zm33-54H65v-13.1l6-6.9v-7h20.5a85.5 85.5 0 0 1 4.6 27Zm-5.7-30H71v-5l5-4v-9.2A40.3 40.3 0 0 1 90.3 90ZM51 71.8V81l5 4v5H36.7c3-7 7.5-13.6 14.3-18.2ZM35.5 93H56v7l6 6.9V120H31a85.5 85.5 0 0 1 4.5-27Z"/>
<path d="M54 59h19v20l-5 4v16l-4.5 5-4.5-5V83l-5-4V59Z"/>
<path d="M73 33h-4c0-3.9-2.5-7-5.5-7S58 29.1 58 33h-4c0-9.6 4-10 4-10s-4-4-4-12h4s.8 8 5 8h.6c4.4 0 5.2-8 5.2-8H73c0 8-4.2 12-4.2 12s4.2.4 4.2 10Zm0 0h-4c0 3.9-2.5 7-5.5 7S58 36.9 58 33h-4c0 9.6 4 10 4 10s-4 4-4 12h4s.8-8 5-8h.6c4.4 0 5.2 8 5.2 8H73c0-8-4.2-12-4.2-12s4.2-.4 4.2-10Z"/>
</svg>

After

Width:  |  Height:  |  Size: 954 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M94.5 93h15.3a53.7 53.7 0 0 1 7.2 27H99c-.4-11-2-19.9-4.5-27ZM74.2 67.2A54 54 0 0 1 107.9 90H93.4c-5.3-13-13-19.5-19.2-22.8ZM90.3 90H65V67a37 37 0 0 1 25.3 23Zm-54.8 3H62v27H31a85.5 85.5 0 0 1 4.5-27ZM62 67v23H36.7A37 37 0 0 1 62 67ZM33.6 90H18.1a54 54 0 0 1 35.3-23.1A42.4 42.4 0 0 0 33.6 90Zm-5.5 30H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27Zm67.5 43a54 54 0 0 1-65.2 0h65.2Zm-4-70a85.5 85.5 0 0 1 4.5 27H65V93h26.5Z"/>
<path d="M106 83S91.3 63.5 63 64c-28.4-.5-44 20-44 20s-5-15 1-22c7.3-8.6 19.2-5.1 21-5 3 .2 2-1 2-1s-2.8-3.6-7-3c-9.5 1.4-5-6-5-6 5.9-9.8 19.6-6 23.2-5.3 1.3.3.8-.7.8-.7s-5.9-2.3-6-5c-.4-9.7 14-8 14-8h.5c2.6-.1 13.8-.5 13.4 8.1 0 2.7-6 5-6 5s-.4 1 .9.7c3.5-.8 17.2-4.5 23 5.3 0 0 4.5 7.4-5 6-4.1-.7-6.9 3-6.9 3s-1 1.2 2 1c1.7-.2 13.6-3.6 20.9 5 5.9 6.9.2 20.9.2 20.9Z"/>
</svg>

After

Width:  |  Height:  |  Size: 914 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#de7b6c" d="M94.5 93h15.3a53.7 53.7 0 0 1 7.2 27H99c-.4-11-2-19.9-4.5-27ZM74.2 67.2A54 54 0 0 1 107.9 90H93.4c-5.3-13-13-19.5-19.2-22.8ZM90.3 90H65V67a37 37 0 0 1 25.3 23Zm-54.8 3H62v27H31a85.5 85.5 0 0 1 4.5-27ZM62 67v23H36.7A37 37 0 0 1 62 67ZM33.6 90H18.1a54 54 0 0 1 35.3-23.1A42.4 42.4 0 0 0 33.6 90Zm-5.5 30H9a53.7 53.7 0 0 1 7.2-27h16.3c-2.4 7.1-4.1 16-4.4 27Zm67.5 43a54 54 0 0 1-65.2 0h65.2Zm-4-70a85.5 85.5 0 0 1 4.5 27H65V93h26.5Z"/>
<path d="M62 14h3v50h-3zM71 14h3v3h-3zM71 24h3v3h-3zM71 33h3v3h-3zM71 42h3v3h-3zM71 51h3v3h-3zM71 60h3v3h-3z"/>
<path d="m49.6 58.3 4-.5.8 6-4 .4Z"/>
<path d="m39.1 60.8 3.8-1.3 2 5.7-3.8 1.3Z"/>
<path d="m28.7 66.6 3.3-2.2 3.3 5-3.3 2.2Z"/>
<path d="m20.5 73.1 3-2.7 4 4.5-3 2.7Z"/>
</svg>

After

Width:  |  Height:  |  Size: 829 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path d="M78 32h8l-8 7v-7"/>
<path d="M78 19h8l-8-7v7"/>
<path d="M114 30H78v-9h36s5 .5 5 4v1c0 3.5-5 4-5 4Z"/>
<path fill="#49adc9" d="M81 103v4l6 6 1 1H65l1-1 6-6v-8l6-7V78h9v18Zm-7-16-6 7H58l-6-7V74H39V58l4-4h8l5-4h14l5 4h8l4 4v16H74v13Zm-4-29H56v12h14V58ZM48 92l6 7v8l6 6 1 1H38l1-1 6-6v-4l-6-7V78h9v14Z"/>
<path d="M8 37h26l2-2h7l6-3-6-3h-7l-2-2H8v10Z"/>
<path d="M8 23h26l2-2h7l6-3-6-3h-7l-2-2H8v10Z"/>
</svg>

After

Width:  |  Height:  |  Size: 497 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#c9b269" d="M4 122v-20l20 20H4Zm118 0v-20l-20 20h20Zm0-118v20L102 4h20ZM4 4v20L24 4H4Z"/>
<path d="M36 50.8c.1-.5.6-1.8 3-1.8h20V14a1.9 1.9 0 0 1 1.8-2h4.4a1.9 1.9 0 0 1 1.8 2v35h20c3 0 3 2 3 2v3l-4.3 10.1Zm33.5 51-14.7-4-4.8-11 23.3 6.1ZM63 117l-6.2-14.5 11.1 3ZM48 82 43.2 71l35.5 9.5-3.8 8.8ZM36.5 55 84 67.9l-3.8 8.9-39-10.5Z"/>
</svg>

After

Width:  |  Height:  |  Size: 429 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill-rule="evenodd">
<path
d="m29 69 8 .012A.98.98 0 0 0 38 70h1a.967.967 0 0 0 1-1h3a.977.977 0 0 0 1 1h1a.951.951 0 0 0 1-1s-.258-1 3-1c0 0 1-.146 1 2v8h6l2 2s3 .016 3 1a11.256 11.256 0 0 1 3 0c1.526.229 3.038-3 8-3s7 3 7 3h2a1.963 1.963 0 0 1 2-1c2.092.009 13 1 13 1l8-1v1h4a40.413 40.413 0 0 1 6-1c1.83-.024 2 2 2 2a13.018 13.018 0 0 1 1 9s-2.3 2.2-6 0h-5l-1 1H95s-.868.934 1 1c0 0 .959 1-5 1l-1 1h-7v1h-1l-1 8s-3.411 1.326-3-1 1-7 1-7l-1-2h-1v3h-9v3s.893.522 0 1-.694 1.152-3 1v2l-2 2 1 2-7-3 6-6a1.665 1.665 0 0 0-2-2l-1-1v-2h-2v1h-4l-2 3h-5s-.978.26-1 2 .45 6.547-3 7a1.322 1.322 0 0 1-2 0c-.9-1.1-.745-11.807-12-12l-1-1H16l-2-1v1s-1.418 1.42-5 0c-1.885-.747-1.35-13.582 0-15 2.185-2.3 7 0 7 0V69l1-1h3l1 1h8z"
fill="#49adc9" />
<path
d="M94 38v-4h10v4H94Zm-4.95-12.828 7.071-7.072 2.828 2.828L91.879 28ZM81 46a10 10 0 0 1-9.541-7H23v-6h48.459A10 10 0 1 1 81 46Zm-2-33h4v10h-4V13Zm-15.993 7.852 2.855-2.864L73 25.148l-2.855 2.864Zm10.011 26-7.15 7.161-2.86-2.864 7.15-7.161ZM83 59h-4V49h4v10Zm16.012-7.929L96.179 53.9 89.1 46.828 91.929 44Z"
fill="#fff" />
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#49adc9" d="M121 83v9H81v-2H70v2H49l-2 4h-8l-7 9h-3l-9-8h-8v-1H5V78h37v-1h4v1h5v-1h3v1h2v-1h2v1h2v-1h4v1h11v-1h46v4h-3v2h3Zm-87 8h-6v7h2l4-5v-2Zm11 1h-3v2h3v-2Z"/>
<path d="M62 50V31h24l4 3h15l8 7-8 6H90l-4 3H62Z"/>
<path d="M35 31v4c-3.9 0-7 2.5-7 5.5s3.1 5.5 7 5.5v4c-9.6 0-10-4-10-4s-4 4-12 4v-4s8-.8 8-5v-.6c0-4.4-8-5.2-8-5.2V31c8 0 12 4.2 12 4.2s.4-4.2 10-4.2Zm0 0v4c3.9 0 7 2.5 7 5.5S38.9 46 35 46v4c9.6 0 10-4 10-4s4 4 12 4v-4s-8-.8-8-5v-.6c0-4.4 8-5.2 8-5.2V31c-8 0-12 4.2-12 4.2S44.6 31 35 31Z"/>
</svg>

After

Width:  |  Height:  |  Size: 603 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill-rule="evenodd" fill="#49adc9" d="M39 75v-2h50v2h32v15h-4v1h-10v-1H96v1h6v2h-8l-3 8H81v-5h-2l-7 10-4-4 7-10H50v17h-5V99l-4-5h-6l-1-2H24l-1-2h-3l-9 5H6l-2-2V74l2-2h5l9 3h19Zm43 18 2-2 4 4-2 2Z"/>
<path d="M79 50c-5.3 0-30-7-30-7H35l-4 9H17l5-12v-1l-5-12h14l4 9h14s24.7-7 30-7 28 7 28 7v7s-22.7 7-28 7Z"/>
</svg>

After

Width:  |  Height:  |  Size: 398 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126">
<path fill="#fff" fill-rule="evenodd" d="M85 108H23l-8-9V89h17l10 9h24l10-9h17v10zM54 94 31 77V57h4c0-18.7 19-19 19-19s19 .3 19 19h4v20zm14-37H40v14h7l3-4h8l3 4h7V57zm48-15h-16v16h-7V42H77v-7h16V19h7v16h16v7z"/>
<path fill="#c9b269" fill-rule="evenodd" d="M4 122v-20l20 20H4Zm118 0v-20l-20 20h20Zm0-118v20L102 4h20ZM4 4v20L24 4H4Z"/>
</svg>

After

Width:  |  Height:  |  Size: 416 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#c9b269" d="M82 52V24h30L96.4 52H82Zm-50.4 0L16 24h30v28H31.6Zm44.7 36L64 110 51.7 88h24.6Z"/>
<path d="M34 84V56h9v10h10V56h9v28H34ZM66 84V56h9v10h10V56h9v28H66ZM50 52V24h9v10h10V24h9v28H50Z"/>
<path fill="#c9b269" d="M5 123v-20l20 20H5Zm118 0v-20l-20 20h20Zm0-118v20L103 5h20ZM5 5v20L25 5H5Z"/>
</svg>

After

Width:  |  Height:  |  Size: 394 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M90 33s-6-8.3-18-15h43v15H90Zm2 24v14H50.6l-.6-6 17-17V28H47L31 43.1V18h22s39 0 39 39Zm-7 35H41v-7l9-9h35v16Zm8 4 13 16H18l13-16h62Z"/>
<path d="M63 32v14L46 63v10L34 85V61H10l12-12h10l17-17h14Z"/>
<path d="M20 86v-9l6-6v10ZM24 69l-6 5H9l5-5h10Z"/>
</svg>

After

Width:  |  Height:  |  Size: 358 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill-rule="evenodd">
<path fill="#c9b269" d="M94.47 92h15.288A53.737 53.737 0 0 1 117 119H98.924c-.329-11.02-2.004-19.88-4.454-27zM74.191 66.2A53.991 53.991 0 0 1 107.9 89H93.357c-5.213-12.973-13.046-19.528-19.166-22.8zM90.327 89H65V66c13.307 3.34 20.946 12.73 25.327 23zM35.5 92H62v27H30.912A85.548 85.548 0 0 1 35.5 92zM62 66v23H36.681C41.065 78.73 48.7 69.343 62 66zM33.635 89H18.1a53.974 53.974 0 0 1 35.28-23.1c-6.199 3.159-14.367 9.7-19.745 23.1zm-5.559 30H9a53.731 53.731 0 0 1 7.242-27h16.281c-2.446 7.12-4.123 15.98-4.447 27zm67.569 43a53.939 53.939 0 0 1-65.289 0h65.288zm-4.136-70a85.481 85.481 0 0 1 4.58 27H65V92h26.509z"/>
<path fill="#fff" d="M54 38V10H29l18 28h7zm19-28h25L80 38h-7V10zm-14 0h9v33h9L64 63 50 43h9"/>
</svg>

After

Width:  |  Height:  |  Size: 813 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<g fill="#49adc9">
<path d="M79 41h9v10h-9z"/>
<path d="M75 41H64l-10-9v14l11 4v48h39l9-9V32l-10 9H92v14H75V41Z"/>
<path d="m54 27 11 10h37l11-10V16H54v11Z"/>
</g>
<path d="M8 99s24 16 26 16 26-16 26-16V53s-22-6-26-6-26 6-26 6v46Zm15-18 15-21-5 17h12L30 97l5-16H23Z"/>
</svg>

After

Width:  |  Height:  |  Size: 366 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M121 121H5v-20l17-7 20 10 21-10 21 10 20-10 17 7.2V121Z"/>
<path d="M37 75s24 16 26 16 26-16 26-16V29s-22-6-26-6-26 6-26 6v46Zm15-18 15-21-5 17h12L59 73l5-16H52Z"/>
</svg>

After

Width:  |  Height:  |  Size: 275 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" viewBox="0 0 126 126">
<path fill="#c9b269" d="M4 122v-20l20 20H4Zm118 0v-20l-20 20h20Zm0-118v20L102 4h20ZM4 4v20L24 4H4Z"/>
<path fill="#fff" d="M63 48s-9.206.521-14 6c0 0-2.527 1.473-4 0s0-4 0-4a27.841 27.841 0 0 1 18-7v5zm0 0s9.376.684 14.258 6.324c0 0 2.574 1.516 4.074 0s0-4.118 0-4.118A28.213 28.213 0 0 0 63 43v5zm0-9s13.118.36 18 6c0 0 4.832 3.841 6.332 2.324.6-.608 1.768-1.8.668-3.324-1.644-2.286-6-5-6-5a39.028 39.028 0 0 0-19-5v5zm0 0s-12.892.495-17.69 6.277c0 0-4.749 3.937-6.223 2.383-.591-.623-1.737-1.841-.657-3.408 1.615-2.343 5.9-5.126 5.9-5.126A37.218 37.218 0 0 1 63 34v5zm0-9s-18.2 2.218-23 8c0 0-4.407 4.468-7 3-.747-.423-1.081-2.433 0-4 1.615-2.343 9-7 9-7s10.172-5 21-5v5zm0 0s18.387 2.079 23.234 7.751c0 0 4.452 4.383 7.071 2.943.755-.415 1.092-2.386 0-3.923-1.632-2.3-9.092-6.866-9.092-6.866S73.938 25 63 25v5zM45 71s-.338 1-3 1a7.075 7.075 0 0 1-4-1 11.323 11.323 0 0 0 0-4 1.6 1.6 0 0 0-1-1h-6c-2.025 0-.465 4.5 1 6 1.88 1.912 4.453 1.528 10 6a8.853 8.853 0 0 1 3 8s1.181 9-12 9-10-12-10-12 .339-1 3-1a7.031 7.031 0 0 1 4 1 11.308 11.308 0 0 0 0 4 1.605 1.605 0 0 0 1 1h5a1.936 1.936 0 0 0 2-2s1.477-3.839-4-6c-6.467-2.552-8.921-5.5-10-7a.564.564 0 0 1-.106-.389A22.684 22.684 0 0 1 23.031 68c.039-1.465-1.179-9 11.984-9S45 71 45 71zm56 0s-.338 1-3 1a7.075 7.075 0 0 1-4-1 11.323 11.323 0 0 0 0-4 1.6 1.6 0 0 0-1-1h-6c-2.025 0-.465 4.5 1 6 1.88 1.912 4.453 1.528 10 6a8.853 8.853 0 0 1 3 8s1.181 9-12 9-10-12-10-12 .339-1 3-1a7.031 7.031 0 0 1 4 1 11.308 11.308 0 0 0 0 4 1.605 1.605 0 0 0 1 1h5a1.936 1.936 0 0 0 2-2s1.477-3.839-4-6c-6.467-2.552-8.921-5.5-10-7a.564.564 0 0 1-.106-.389A22.684 22.684 0 0 1 79.031 68c.039-1.465-1.179-9 11.984-9S101 71 101 71zM70 94H55c-3.154 0-4-5-4-5l.143-12L51 65s.846-5 4-5h15c3.255 0 4 5 4 5v24s-.745 5-4 5zm-7.5-5c-1.374.026-4.5.723-4.5-2V75.908l-.044-8.9c-.017-2.72 3.17-2.034 4.544-2.008 1.374-.026 4.5-.723 4.5 2v20c0 2.724-3.126 2.026-4.5 2z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill-rule="evenodd" d="M24 26h15L24 13v13ZM24 53h15L24 66V53ZM24 30h73s9 1 9 10-9 9-9 9H24V30Zm71.5 4a5.5 5.5 0 1 1-5.5 5.5 5.5 5.5 0 0 1 5.5-5.5Z"/>
<path fill="#49adc9" d="m110 95-3 3h-9l-4 11h-3l-3-3h-3v3h-6l-6-3h-1l-9 9h-4L48 98H34l-3-3H14V84h19v-3h7v-3h42v-2h24v2h1v4h5v13h-2Zm-49 5v8l8-8h-8Zm20 3h-5v3l5 1v-4Z"/>
</svg>

After

Width:  |  Height:  |  Size: 409 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126"><g><path fill="#49adc9" fill-rule="evenodd" d="m80 81 3 3h30l2 2h3v1h3v1h-3l-1 1v1h2v1h-4l-3 5h-3v-1h-2v1H94v-1h-2v1h-2v-1l-2-1-3 3h-8v8H65v-8h-8l-3 3h-7s-3.855 5.6-3 8c.984 2.76-2 3-2 3l-5-3s-.774-2.848 0-4c.748-1.113 6-6 6-6v-4h-7l-1-1h-8l-4 4H10l-2 2H6l-1-1V83l1-1h30l7-1v-1h4v1h2v-1h2v1h1v-1h6v1h3v-1h1v1h2v-1h1v1h15ZM49 94h6v2l-2 2h-4v-4Z"/><path d="M45 61h26l2-2h8l5-2.469L81 54h-8l-2-2H45v9Z" fill="#fff" fill-rule="evenodd"/><path d="M45 48h26l2-2h8l5-2.469L81 41h-8l-2-2H45v9Z" fill="#fff" fill-rule="evenodd"/><path d="M45 35h26l2-2h8l5-2.469L81 28h-8l-2-2H45v9Z" fill="#fff" fill-rule="evenodd"/></g></svg>

After

Width:  |  Height:  |  Size: 679 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill-rule="evenodd" d="M7 59h17v19h20V59h17v54H7V59Zm7 29h19v2a1 1 0 0 0 1 1h14s6 2.4 6 4.6-6 4.4-6 4.4H34a1 1 0 0 0-1 1v2H14V88Z"/>
<g fill="#49adc9">
<path d="M79 41h9v10h-9z"/>
<path d="M75 41H63l-9-9v23h11v43h39l9-9V32l-9 9H92v14H75V41Z"/>
<path d="m54 27 11 10h37l11-10V16H54v11Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 396 B

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#679552" d="M-9 140v-39l9 2v23h126v-22.7l4 1.7 3 35H-9Zm130-19H5v-20l17-7 20 10 21-10 21 10 20-10 17 7.2V121Z"/>
<path d="m33 94 9 5 21-10 21 10 9-5-8-11V43h-7v31H68V64l-3-3V51h-4v10l-3 3v10H48V43h-7v40Z"/>
<path d="M72 27 57 47l5-16H50l15-21-5 17h12Z"/>
</svg>

After

Width:  |  Height:  |  Size: 355 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 126 126" fill="#fff">
<path fill="#c9b269" d="M4 122v-20l20 20H4Zm118 0v-20l-20 20h20Zm0-118v20L102 4h20ZM4 4v20L24 4H4Z"/>
<path d="M9 78v10l10 10h88l10-10V78H73v14H53V78H9ZM26 74V28h74v46H26Zm37-40L41 57h12v14h20V57h12Z"/>
</svg>

After

Width:  |  Height:  |  Size: 287 B

+316 -75
View File
@@ -13,6 +13,7 @@
<!-- ── Navigation ─────────────────────────────────────────────── -->
<nav id="main-nav" class="hidden">
<button id="nav-hamburger" aria-label="Open menu" aria-expanded="false">&#9776;</button>
<div class="nav-brand">
<span class="nav-logo"></span>
<span>HELLDIVERS 2</span>
@@ -20,6 +21,7 @@
<div class="nav-links">
<button class="nav-btn" data-view="dashboard">Dashboard</button>
<button class="nav-btn" data-view="practice">Training</button>
<button class="nav-btn" data-view="history">History</button>
<button class="nav-btn" data-view="lobby">1v1</button>
<button class="nav-btn" data-view="leaderboard">Highscores</button>
<button class="nav-btn nav-btn-admin hidden" id="nav-admin" data-view="admin">Admin</button>
@@ -30,14 +32,32 @@
</div>
</nav>
<!-- ── Mobile drawer ──────────────────────────────────────────── -->
<div id="nav-overlay"></div>
<nav id="nav-drawer" role="navigation" aria-label="Mobile navigation">
<div class="drawer-header">⚡ HELLDIVERS 2</div>
<button class="drawer-btn" data-view="dashboard">Dashboard</button>
<button class="drawer-btn" data-view="practice">Training</button>
<button class="drawer-btn" data-view="history">History</button>
<button class="drawer-btn" data-view="lobby">1v1 Arena</button>
<button class="drawer-btn" data-view="leaderboard">Highscores</button>
<button class="drawer-btn drawer-btn-admin hidden" id="drawer-admin" data-view="admin">Admin</button>
<div class="drawer-footer">
<button class="btn btn-muted btn-full btn-sm" id="btn-logout-drawer">Logout</button>
</div>
</nav>
<!-- Incoming challenge badge (shown anywhere) -->
<div id="challenge-badge" class="challenge-badge hidden"></div>
<!-- Score popup (practice) -->
<div id="score-popup" class="score-popup hidden"></div>
<!-- ── LOGIN ─────────────────────────────────────────────────── -->
<div id="view-login" class="view view-centered">
<div class="login-box">
<div class="login-header">
<div class="login-logo"></div>
<span class="login-logo"></span>
<h1>HELLDIVERS 2</h1>
<p class="login-sub">STRATAGEM TRAINER — SUPER EARTH AUTHORIZED</p>
</div>
@@ -60,7 +80,7 @@
<div id="view-change-password" class="view view-centered hidden">
<div class="login-box">
<div class="login-header">
<h2>CHANGE ACCESS CODE</h2>
<h2 style="font-family:var(--font-heading);font-size:1.4rem;letter-spacing:.1em;color:var(--accent)">CHANGE ACCESS CODE</h2>
<p class="login-sub">Temporary password must be changed before proceeding</p>
</div>
<form id="change-password-form" class="login-form">
@@ -84,126 +104,254 @@
<!-- ── DASHBOARD ─────────────────────────────────────────────── -->
<div id="view-dashboard" class="view hidden">
<div class="page-header">
<h2 class="page-title">COMMAND CENTER</h2>
<p class="page-sub">Welcome back, Helldiver. For Super Earth.</p>
</div>
<div class="dashboard-grid">
<!-- Stats card -->
<div class="card">
<h3 class="card-title">YOUR STATS</h3>
<div class="stat-grid">
<div class="stat-item">
<div class="stat-value" id="dash-total-score"></div>
<div class="stat-label">Total Score</div>
<!-- Hero card -->
<div class="card card-hero dashboard-hero">
<div class="hero-identity">
<div class="hero-rank-icon" id="dash-rank-icon"></div>
<div>
<div class="hero-name" id="dash-hero-name"></div>
<div class="hero-rank-name" id="dash-rank-label">PRIVATE</div>
</div>
<div class="stat-item">
<div class="stat-value accent" id="dash-rank"></div>
<div class="stat-label">Global Rank</div>
</div>
<div class="hero-elo">ELO <span id="dash-elo">1000</span></div>
<div class="hero-stats">
<div class="hero-stat-item">
<div class="hero-stat-val" id="dash-total-score"></div>
<div class="hero-stat-label">Total Score</div>
</div>
<div class="stat-item">
<div class="stat-value" id="dash-sessions"></div>
<div class="stat-label">Sessions</div>
<div class="hero-stat-item">
<div class="hero-stat-val" id="dash-rank"></div>
<div class="hero-stat-label">Global Rank</div>
</div>
<div class="stat-item">
<div class="stat-value" id="dash-win-rate"></div>
<div class="stat-label">Match Win Rate</div>
<div class="hero-stat-item">
<div class="hero-stat-val" id="dash-sessions"></div>
<div class="hero-stat-label">Sessions</div>
</div>
<div class="hero-stat-item">
<div class="hero-stat-val" id="dash-win-rate"></div>
<div class="hero-stat-label">Win Rate</div>
</div>
</div>
</div>
<!-- Daily challenge card -->
<div class="card card-accent">
<h3 class="card-title">⚡ DAILY CHALLENGE</h3>
<h3 class="card-title">Daily Challenge</h3>
<div class="daily-stratagem">
<div class="daily-icon-wrap">
<img id="dash-daily-icon" class="stratagem-icon-md" src="" alt="" style="display:none">
</div>
<div class="daily-name" id="dash-daily-name"></div>
<div class="daily-category" id="dash-daily-category"></div>
<div class="daily-best">
Best time: <span id="dash-daily-best"></span>
</div>
<button class="btn btn-accent" id="btn-daily-challenge">Practice this stratagem</button>
<div class="daily-sequence-preview" id="dash-daily-sequence"></div>
<div class="daily-best">Personal best: <span id="dash-daily-best"></span></div>
<button class="btn btn-accent btn-sm" id="btn-daily-challenge">⚡ Practice Now</button>
</div>
</div>
<!-- Online users card -->
<!-- Online players -->
<div class="card">
<h3 class="card-title">ONLINE HELLDIVERS</h3>
<h3 class="card-title">Online Helldivers</h3>
<div id="dash-online" class="online-list">
<span class="muted">Loading...</span>
</div>
</div>
<!-- Recent sessions card -->
<!-- Recent sessions -->
<div class="card">
<h3 class="card-title">RECENT SESSIONS</h3>
<h3 class="card-title">Recent Sessions</h3>
<table class="data-table">
<thead>
<tr><th>Stratagem</th><th>Score</th><th>Time</th></tr>
<tr><th>Stratagem</th><th>Mode</th><th>Score</th><th>Time</th></tr>
</thead>
<tbody id="dash-recent">
<tr><td colspan="3" class="muted">No sessions yet</td></tr>
<tr><td colspan="4" class="muted">No sessions yet</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- ── PRACTICE ───────────────────────────────────────────────── -->
<div id="view-practice" class="view hidden">
<div class="page-header">
<h2 class="page-title">TRAINING PROTOCOL</h2>
<div class="practice-header">
<div>
<h2 class="page-title">TRAINING PROTOCOL</h2>
<p class="page-sub" id="practice-mode-label">Select a mode to begin</p>
</div>
<button class="btn btn-ghost btn-icon" id="btn-practice-settings" aria-label="Practice settings" data-tooltip="Settings"></button>
</div>
<!-- Mode selector -->
<div id="practice-mode-grid" class="mode-grid">
<div class="mode-card active" data-mode="timed">
<div class="mode-icon"></div>
<div class="mode-name">Timed</div>
<div class="mode-desc">30s per stratagem. Score by speed.</div>
</div>
<div class="mode-card" data-mode="endless">
<div class="mode-icon"></div>
<div class="mode-name">Endless</div>
<div class="mode-desc">3 lives. No timer. How far can you go?</div>
</div>
<div class="mode-card" data-mode="drill">
<div class="mode-icon">🎯</div>
<div class="mode-name">Category Drill</div>
<div class="mode-desc">Master one category completely.</div>
</div>
<div class="mode-card" data-mode="speedrun">
<div class="mode-icon"></div>
<div class="mode-name">Speed Run</div>
<div class="mode-desc">All stratagems, fastest total time.</div>
</div>
</div>
<!-- Category filters -->
<div class="category-row" id="practice-categories"></div>
<!-- Idle (start screen) -->
<div id="practice-idle" class="practice-idle">
<div class="idle-hint">Select categories above, then start training</div>
<button class="btn btn-accent btn-lg" id="btn-start-practice">⚡ START TRAINING</button>
<!-- Idle -->
<div id="practice-idle" class="practice-setup">
<div class="idle-hint" id="practice-idle-hint">Select categories above, then start training</div>
<div class="practice-start-row">
<button class="btn btn-accent btn-lg" id="btn-start-practice">⚡ START TRAINING</button>
</div>
</div>
<!-- Active training -->
<div id="practice-active" class="practice-active hidden">
<!-- Drill progress bar -->
<div id="drill-progress-wrap" class="drill-progress hidden">
<div class="drill-label">
<span>Category Progress</span>
<span id="drill-progress-text">0 / 0</span>
</div>
<div class="progress-bar">
<div class="progress-fill" id="drill-progress-fill" style="width:0%"></div>
</div>
</div>
<div class="stratagem-display card">
<!-- Stratagem icon -->
<div class="stratagem-icon-wrap">
<img id="practice-icon" class="stratagem-icon-lg" src="" alt="" style="display:none">
<div id="practice-icon-fallback" class="stratagem-icon-fallback"></div>
</div>
<div class="stratagem-category" id="practice-category"></div>
<div class="stratagem-name" id="practice-name"></div>
<div class="arrow-sequence" id="practice-sequence"></div>
<div class="practice-hint">Use Arrow Keys or D-Pad</div>
<div class="practice-hint">Arrow Keys or D-Pad · <kbd>Esc</kbd> to stop</div>
</div>
<!-- Upcoming queue -->
<div class="stratagem-queue" id="practice-queue"></div>
<div class="practice-hud">
<div class="hud-item">
<div class="hud-label">TIME</div>
<div class="timer" id="practice-timer">30</div>
<!-- Timer ring / lives / elapsed -->
<div class="hud-item" id="hud-timer-wrap">
<div class="hud-label" id="hud-timer-label">TIME</div>
<div class="timer-ring-wrap">
<svg class="timer-ring-svg" viewBox="0 0 80 80">
<circle class="timer-ring-bg" cx="40" cy="40" r="35"/>
<circle class="timer-ring-fill" id="timer-ring-fill" cx="40" cy="40" r="35"
stroke-dasharray="219.9" stroke-dashoffset="0"/>
</svg>
<div class="timer-ring-val" id="practice-timer">30</div>
</div>
</div>
<!-- Lives (endless mode) -->
<div class="hud-item hidden" id="hud-lives-wrap">
<div class="hud-label">LIVES</div>
<div class="lives-display" id="practice-lives">
<span class="life-icon"></span>
<span class="life-icon"></span>
<span class="life-icon"></span>
</div>
</div>
<div class="hud-item">
<div class="hud-label">SCORE</div>
<div class="hud-value" id="practice-score">0</div>
</div>
<div class="hud-item">
<div class="hud-item" id="hud-streak-item">
<div class="hud-label">STREAK</div>
<div class="hud-value accent" id="practice-streak">0</div>
<div class="combo-badge hidden" id="practice-combo">×1.0</div>
</div>
</div>
<!-- D-Pad (mobile) -->
<!-- D-Pad -->
<div class="dpad" id="practice-dpad">
<div class="dpad-row">
<button class="dpad-btn dpad-up" data-dir="up"></button>
<button class="dpad-btn" data-dir="up" aria-label="Arrow up"></button>
</div>
<div class="dpad-row">
<button class="dpad-btn dpad-left" data-dir="left"></button>
<button class="dpad-btn" data-dir="left" aria-label="Arrow left"></button>
<div class="dpad-center"></div>
<button class="dpad-btn dpad-right" data-dir="right"></button>
<button class="dpad-btn" data-dir="right" aria-label="Arrow right"></button>
</div>
<div class="dpad-row">
<button class="dpad-btn dpad-down" data-dir="down"></button>
<button class="dpad-btn" data-dir="down" aria-label="Arrow down"></button>
</div>
</div>
<button class="btn btn-muted" id="btn-stop-practice">Stop Training</button>
<button class="btn btn-muted btn-sm" id="btn-stop-practice">Stop Training</button>
</div>
</div>
<!-- ── HISTORY ────────────────────────────────────────────────── -->
<div id="view-history" class="view hidden">
<div class="page-header">
<h2 class="page-title">MISSION LOGS</h2>
<p class="page-sub">Your practice history and stratagem statistics</p>
</div>
<div class="card" style="margin-bottom:16px">
<h3 class="card-title">Score Progression</h3>
<div class="history-chart" id="history-chart">
<svg id="history-chart-svg" width="100%" height="100%" preserveAspectRatio="none"></svg>
</div>
</div>
<div class="card">
<div class="history-filters">
<select id="history-filter-mode">
<option value="">All Modes</option>
<option value="timed">Timed</option>
<option value="endless">Endless</option>
<option value="drill">Category Drill</option>
<option value="speedrun">Speed Run</option>
</select>
<select id="history-filter-cat">
<option value="">All Categories</option>
</select>
</div>
<h3 class="card-title">Session History</h3>
<table class="data-table">
<thead>
<tr><th>Stratagem</th><th>Category</th><th>Mode</th><th>Score</th><th>Time</th><th>Date</th></tr>
</thead>
<tbody id="history-table-body">
<tr><td colspan="6" class="muted">Loading...</td></tr>
</tbody>
</table>
<div class="pagination" id="history-pagination"></div>
</div>
<div class="card" style="margin-top:16px">
<h3 class="card-title">Best Times per Stratagem</h3>
<table class="data-table">
<thead>
<tr><th></th><th>Stratagem</th><th>Category</th><th>Best Time</th><th>Attempts</th></tr>
</thead>
<tbody id="best-per-stratagem-body">
<tr><td colspan="5" class="muted">No data yet</td></tr>
</tbody>
</table>
</div>
</div>
@@ -216,12 +364,20 @@
<div class="lobby-layout">
<div class="card">
<h3 class="card-title">ONLINE HELLDIVERS</h3>
<h3 class="card-title">Online Helldivers</h3>
<div id="lobby-players" class="player-list">
<p class="muted">Loading...</p>
<div class="lobby-empty">
<div class="lobby-empty-icon">📡</div>
<p>No other Helldivers online.<br>Waiting for reinforcements...</p>
</div>
</div>
</div>
<div class="card">
<h3 class="card-title">Incoming Challenges</h3>
<div id="lobby-challenges" class="challenge-list">
<p class="muted">No incoming challenges</p>
</div>
</div>
<div id="lobby-challenges" class="challenge-list"></div>
</div>
</div>
@@ -246,6 +402,10 @@
<!-- Round area -->
<div id="match-round-area" class="match-round-area hidden">
<!-- Stratagem icon in match -->
<div style="text-align:center;margin-bottom:8px">
<img id="match-icon" class="stratagem-icon-md" src="" alt="" style="display:none">
</div>
<div class="match-sequences">
<div class="match-seq-col">
<div class="match-seq-label">YOU</div>
@@ -256,18 +416,17 @@
<div class="arrow-sequence" id="match-opp-sequence"></div>
</div>
</div>
<!-- D-Pad (mobile) -->
<div class="dpad" id="match-dpad">
<div class="dpad-row">
<button class="dpad-btn dpad-up" data-dir="up"></button>
<button class="dpad-btn" data-dir="up" aria-label="Arrow up"></button>
</div>
<div class="dpad-row">
<button class="dpad-btn dpad-left" data-dir="left"></button>
<button class="dpad-btn" data-dir="left" aria-label="Arrow left"></button>
<div class="dpad-center"></div>
<button class="dpad-btn dpad-right" data-dir="right"></button>
<button class="dpad-btn" data-dir="right" aria-label="Arrow right"></button>
</div>
<div class="dpad-row">
<button class="dpad-btn dpad-down" data-dir="down"></button>
<button class="dpad-btn" data-dir="down" aria-label="Arrow down"></button>
</div>
</div>
</div>
@@ -285,19 +444,19 @@
<p class="page-sub">Top Helldivers ranked by total practice score</p>
</div>
<div class="leaderboard-tabs">
<button class="tab-btn active" data-tab="practice">Practice Score</button>
<button class="tab-btn" data-tab="elo">ELO Rating</button>
<button class="tab-btn" data-tab="speedrun">Speed Run</button>
</div>
<div class="card">
<table class="data-table leaderboard-table">
<thead>
<tr>
<th>#</th>
<th>Helldiver</th>
<th>Total Score</th>
<th>Sessions</th>
<th>Match W/Total</th>
</tr>
<table class="data-table">
<thead id="leaderboard-thead">
<tr><th>#</th><th>Helldiver</th><th>Rank</th><th>Total Score</th><th>Sessions</th><th>Match W/Total</th></tr>
</thead>
<tbody id="leaderboard-table-body">
<tr><td colspan="5" class="muted">Loading...</td></tr>
<tr><td colspan="6" class="muted">Loading...</td></tr>
</tbody>
</table>
</div>
@@ -308,11 +467,9 @@
<div class="page-header">
<h2 class="page-title">ADMIN PANEL</h2>
</div>
<div class="admin-layout">
<!-- Create user -->
<div class="card">
<h3 class="card-title">CREATE HELLDIVER</h3>
<h3 class="card-title">Create Helldiver</h3>
<div class="field">
<label for="new-username">Username</label>
<input id="new-username" type="text" placeholder="helldiver_name" pattern="[a-zA-Z0-9_-]{2,32}">
@@ -328,15 +485,99 @@
<button class="btn btn-accent" id="btn-create-user">Create User</button>
<div id="new-pw-display" class="pw-display hidden"></div>
</div>
<!-- User list -->
<div class="card">
<h3 class="card-title">ACTIVE HELLDIVERS</h3>
<h3 class="card-title">Active Helldivers</h3>
<div id="admin-users" class="admin-user-list">Loading...</div>
</div>
</div>
</div>
<!-- ── PRACTICE SETTINGS MODAL ──────────────────────────────── -->
<div id="modal-settings" class="modal-overlay hidden" role="dialog" aria-modal="true" aria-label="Practice Settings">
<div class="modal">
<div class="modal-header">
<span class="modal-title">⚙ Practice Settings</span>
<button class="modal-close" id="btn-settings-close" aria-label="Close"></button>
</div>
<div class="settings-section">
<span class="settings-label">Timer Duration (Timed mode)</span>
<div class="settings-options">
<button class="settings-option" data-setting="timer" data-value="15">15s</button>
<button class="settings-option active" data-setting="timer" data-value="30">30s</button>
<button class="settings-option" data-setting="timer" data-value="45">45s</button>
</div>
</div>
<div class="settings-section">
<span class="settings-label">Difficulty</span>
<div class="settings-options">
<button class="settings-option" data-setting="difficulty" data-value="easy">Easy<br><small>Shows category</small></button>
<button class="settings-option active" data-setting="difficulty" data-value="normal">Normal<br><small>Name only</small></button>
<button class="settings-option" data-setting="difficulty" data-value="hard">Hard<br><small>No name shown</small></button>
</div>
</div>
</div>
</div>
<!-- ── CHALLENGE MODAL ────────────────────────────────────────── -->
<div id="modal-challenge" class="modal-overlay hidden" role="dialog" aria-modal="true" aria-label="Incoming Challenge">
<div class="modal">
<div class="modal-header">
<span class="modal-title">⚔ Challenge Incoming!</span>
</div>
<p style="color:var(--text-dim);margin-bottom:8px">Challenger:</p>
<p style="font-family:var(--font-mono);font-size:1.2rem;color:var(--accent);margin-bottom:4px" id="modal-challenger-name"></p>
<p style="font-size:0.8rem;color:var(--text-muted);margin-bottom:20px">ELO: <span id="modal-challenger-elo"></span></p>
<div class="modal-actions">
<button class="btn btn-muted" id="btn-decline-challenge">Decline</button>
<button class="btn btn-accent" id="btn-accept-challenge">⚔ Accept</button>
</div>
</div>
</div>
<!-- ── POST-MATCH RESULT MODAL ───────────────────────────────── -->
<div id="modal-match-result" class="modal-overlay hidden" role="dialog" aria-modal="true" aria-label="Match Result">
<div class="modal modal-wide">
<div class="modal-header">
<span class="modal-title">Match Result</span>
</div>
<div style="text-align:center;padding:8px 0 16px">
<div class="result-winner" id="result-winner-text"></div>
</div>
<div class="elo-delta-row">
<span class="elo-delta-old" id="result-elo-old"></span>
<span class="elo-delta-arrow"></span>
<span class="elo-delta-new" id="result-elo-new"></span>
<span class="elo-delta-val" id="result-elo-delta"></span>
</div>
<div style="height:1px;background:var(--border);margin:12px 0"></div>
<div class="round-history" id="result-round-history"></div>
<div class="modal-actions">
<button class="btn btn-muted" id="btn-result-lobby">Back to Lobby</button>
<button class="btn btn-accent" id="btn-result-rematch">⚔ Rematch</button>
</div>
</div>
</div>
<!-- ── SESSION SUMMARY MODAL ─────────────────────────────────── -->
<div id="modal-session-summary" class="modal-overlay hidden" role="dialog" aria-modal="true" aria-label="Session Summary">
<div class="modal modal-wide">
<div class="modal-header">
<span class="modal-title">Session Complete</span>
</div>
<div class="summary-grid" id="summary-grid"></div>
<div style="height:1px;background:var(--border);margin:16px 0"></div>
<h4 style="font-family:var(--font-heading);font-size:0.85rem;letter-spacing:.06em;color:var(--text-muted);margin-bottom:8px">TOP STRATAGEMS</h4>
<div id="summary-top-stratagems"></div>
<div class="modal-actions">
<button class="btn btn-muted" id="btn-summary-dashboard">Dashboard</button>
<button class="btn btn-accent" id="btn-summary-restart">⚡ Play Again</button>
</div>
</div>
</div>
<!-- ── Danger vignette (≤5s) ──────────────────────────────────── -->
<div id="danger-vignette" class="danger-vignette hidden"></div>
<!-- Toast notifications -->
<div id="toast-container"></div>
+245
View File
@@ -1658,4 +1658,249 @@ select option { background: var(--bg-surface2); }
.page-title { font-size: 1.3rem; }
.match-wins { font-size: 1.8rem; }
.match-status-text { font-size: 1.2rem; }
.stratagem-icon-lg { width: 70px; height: 70px; }
}
/* ── Stratagem icons ─────────────────────────────────────────────────────── */
.stratagem-icon-wrap {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10px;
height: 90px;
}
.stratagem-icon-lg {
width: 86px;
height: 86px;
object-fit: contain;
filter: invert(1) sepia(1) saturate(3) hue-rotate(0deg) brightness(1.1);
/* Converts monochrome SVG → gold/yellow to match theme */
opacity: 0.92;
transition: transform 0.25s ease, opacity 0.2s;
}
.stratagem-icon-lg.icon-complete {
transform: scale(1.12);
filter: invert(1) sepia(1) saturate(6) hue-rotate(0deg) brightness(1.3);
}
.stratagem-icon-lg.icon-wrong {
animation: iconShake 0.35s ease;
}
.stratagem-icon-fallback {
font-size: 3rem;
opacity: 0.25;
}
.stratagem-icon-md {
width: 40px;
height: 40px;
object-fit: contain;
filter: invert(1) sepia(1) saturate(3) hue-rotate(0deg) brightness(1.1);
opacity: 0.85;
}
.stratagem-icon-sm {
width: 22px;
height: 22px;
object-fit: contain;
filter: invert(1) sepia(1) saturate(2) hue-rotate(0deg) brightness(1);
opacity: 0.7;
vertical-align: middle;
margin-right: 5px;
}
/* Icon shake animation */
@keyframes iconShake {
0%, 100% { transform: translateX(0); }
20% { transform: translateX(-5px) rotate(-3deg); }
40% { transform: translateX(5px) rotate(3deg); }
60% { transform: translateX(-4px) rotate(-2deg); }
80% { transform: translateX(4px) rotate(2deg); }
}
/* ── Stratagem queue (upcoming stratagems) ───────────────────────────────── */
.stratagem-queue {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
margin: 6px 0 10px;
min-height: 52px;
}
.queue-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
opacity: 0.45;
transition: opacity 0.2s;
}
.queue-item:first-child { opacity: 0.7; }
.queue-icon {
width: 36px;
height: 36px;
object-fit: contain;
filter: invert(1) sepia(1) saturate(2) hue-rotate(0deg) brightness(1);
}
.queue-icon-fallback {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
background: var(--bg-surface2);
border-radius: 6px;
}
.queue-label {
font-size: 0.6rem;
color: var(--text-muted);
max-width: 60px;
text-align: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
/* ── Score popup ─────────────────────────────────────────────────────────── */
.score-popup {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-family: var(--font-heading);
font-size: 2.2rem;
font-weight: 700;
color: var(--accent);
text-shadow: 0 0 20px var(--accent-glow), 0 2px 8px rgba(0,0,0,0.8);
pointer-events: none;
z-index: 900;
opacity: 0;
letter-spacing: 0.05em;
}
.score-popup.show {
animation: scoreFloat 0.9s ease-out forwards;
}
@keyframes scoreFloat {
0% { opacity: 1; transform: translate(-50%, -50%) scale(0.8); }
30% { opacity: 1; transform: translate(-50%, -70%) scale(1.1); }
100% { opacity: 0; transform: translate(-50%, -120%) scale(0.9); }
}
/* ── Session summary modal ───────────────────────────────────────────────── */
.summary-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
margin-bottom: 16px;
}
.summary-stat {
background: var(--bg-surface2);
border: 1px solid var(--border);
border-radius: var(--radius-md);
padding: 12px 8px;
text-align: center;
}
.summary-stat-val {
font-family: var(--font-heading);
font-size: 1.5rem;
font-weight: 700;
color: var(--accent);
}
.summary-stat-label {
font-size: 0.7rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-top: 2px;
}
.summary-top-item {
display: flex;
align-items: center;
gap: 10px;
padding: 6px 0;
border-bottom: 1px solid var(--border-dim);
}
.summary-top-item:last-child { border-bottom: none; }
.summary-top-rank {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--text-muted);
width: 20px;
flex-shrink: 0;
}
.summary-top-name {
flex: 1;
font-size: 0.9rem;
}
.summary-top-time {
font-family: var(--font-mono);
font-size: 0.8rem;
color: var(--accent);
}
/* ── Arrow transition polish ─────────────────────────────────────────────── */
.arrow-key {
transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease, transform 0.12s ease;
}
.arrow-key.active {
transform: scale(1.12);
}
/* ── pw-display ──────────────────────────────────────────────────────────── */
.pw-display {
margin-top: 10px;
padding: 10px 12px;
background: var(--bg-surface2);
border: 1px solid var(--border);
border-radius: var(--radius-md);
font-family: var(--font-mono);
font-size: 0.85rem;
color: var(--accent);
word-break: break-all;
}
/* ── Admin layout ────────────────────────────────────────────────────────── */
.admin-layout {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
.admin-user-list { display: flex; flex-direction: column; gap: 8px; }
.admin-user-row {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 0;
border-bottom: 1px solid var(--border-dim);
}
.admin-user-row:last-child { border-bottom: none; }
@media (max-width: 768px) {
.summary-grid { grid-template-columns: repeat(2, 1fr); }
.admin-layout { grid-template-columns: 1fr; }
.stratagem-icon-lg { width: 70px; height: 70px; }
.stratagem-queue { gap: 8px; }
}
+166
View File
@@ -0,0 +1,166 @@
/**
* Download Helldivers 2 stratagem SVG icons from:
* github.com/nvigneux/Helldivers-2-Stratagems-icons-svg
*
* Run once: node scripts/download-icons.js
*/
import https from 'https';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ICONS_DIR = path.join(__dirname, '..', 'public', 'icons');
const BASE_URL = 'https://raw.githubusercontent.com/nvigneux/Helldivers-2-Stratagems-icons-svg/master';
// Map: our stratagem name → { repo category folder, repo filename (without .svg) }
const ICON_MAP = [
// ── General / PAC ────────────────────────────────────────────────────────
['Reinforce', 'General Stratagems', 'Reinforce'],
['Resupply', 'General Stratagems', 'Resupply'],
['SOS Beacon', 'General Stratagems', 'SOS Beacon'],
['Hellbomb', 'General Stratagems', 'Hellbomb'],
['SEAF Artillery', 'General Stratagems', 'SEAF Artillery'],
['Upload Data', 'General Stratagems', 'Upload Data'],
['Prospecting Drill', 'General Stratagems', 'Prospecting Drill'],
['Orbital Illumination Flare', 'General Stratagems', 'Orbital Illumination Flare'],
// ── Orbital Cannons ───────────────────────────────────────────────────────
['Orbital Gatling Barrage', 'Orbital Cannons', 'Orbital Gatling Barrage'],
['Orbital Airburst Strike', 'Orbital Cannons', 'Orbital Airburst Strike'],
['Orbital 120MM HE Barrage', 'Orbital Cannons', 'Orbital 120MM HE Barrage'],
['Orbital 380MM HE Barrage', 'Orbital Cannons', 'Orbital 380MM HE Barrage'],
['Orbital Walking Barrage', 'Orbital Cannons', 'Orbital Walking Barrage'],
['Orbital Laser', 'Orbital Cannons', 'Orbital Laser'],
['Orbital Railcannon Strike', 'Orbital Cannons', 'Orbital Railcannon Strike'],
// ── Bridge ────────────────────────────────────────────────────────────────
['Orbital Precision Strike', 'Bridge', 'Orbital Precision Strike'],
['Orbital Gas Strike', 'Bridge', 'Orbital Gas Strike'],
['Orbital EMS Strike', 'Bridge', 'Orbital EMS Strike'],
['Orbital Smoke Strike', 'Bridge', 'Orbital Smoke Strike'],
['Tesla Tower', 'Bridge', 'Tesla Tower'],
['Shield Generator Relay', 'Bridge', 'Shield Generator Relay'],
['HMG Emplacement', 'Bridge', 'HMG Emplacement'],
// ── Hangar ────────────────────────────────────────────────────────────────
['Eagle Strafing Run', 'Hangar', 'Eagle Strafing Run'],
['Eagle Airstrike', 'Hangar', 'Eagle Airstrike'],
['Eagle Cluster Bomb', 'Hangar', 'Eagle Cluster Bomb'],
['Eagle Napalm Airstrike', 'Hangar', 'Eagle Napalm Airstrike'],
['LIFT-850 Jump Pack', 'Hangar', 'Jump Pack'],
['Eagle Smoke Strike', 'Hangar', 'Eagle Smoke Strike'],
['Eagle 110MM Rocket Pods', 'Hangar', 'Eagle 110MM Rocket Pods'],
['Eagle 500KG Bomb', 'Hangar', 'Eagle 500KG Bomb'],
['Eagle Rearm', 'Hangar', 'Eagle Rearm'],
// ── PAC Support Weapons ─────────────────────────────────────────────────
['Machine Gun', 'Patriotic Administration Center', 'Machine Gun'],
['Anti-Materiel Rifle', 'Patriotic Administration Center', 'Anti-Materiel Rifle'],
['Stalwart', 'Patriotic Administration Center', 'Stalwart'],
['Expendable Anti-Tank', 'Patriotic Administration Center', 'Expendable Anti-Tank'],
['Recoilless Rifle', 'Patriotic Administration Center', 'Recoilless Rifle'],
['Flamethrower', 'Patriotic Administration Center', 'Flamethrower'],
['Autocannon', 'Patriotic Administration Center', 'Autocannon'],
['Heavy Machine Gun', 'Patriotic Administration Center', 'Heavy Machine Gun'],
['Airburst Rocket Launcher', 'Patriotic Administration Center', 'Airburst Rocket Launcher'],
['Commando', 'Patriotic Administration Center', 'Commando'],
['Railgun', 'Patriotic Administration Center', 'Railgun'],
['Spear', 'Patriotic Administration Center', 'Spear'],
// ── Engineering Bay ───────────────────────────────────────────────────────
['Quasar Cannon', 'Engineering Bay', 'Quasar Cannon'],
['Arc Thrower', 'Engineering Bay', 'Arc Thrower'],
['Laser Cannon', 'Engineering Bay', 'Laser Cannon'],
['Grenade Launcher', 'Engineering Bay', 'Grenade Launcher'],
['Supply Pack', 'Engineering Bay', 'Supply Pack'],
['Guard Dog Rover', 'Engineering Bay', 'Guard Dog Rover'],
['Ballistic Shield Backpack', 'Engineering Bay', 'Ballistic Shield Backpack'],
['Shield Generator Pack', 'Engineering Bay', 'Shield Generator Pack'],
['Anti-Personnel Minefield', 'Engineering Bay', 'Anti-Personnel Minefield'],
['Incendiary Mines', 'Engineering Bay', 'Incendiary Mines'],
['Anti-Tank Mines', 'Engineering Bay', 'Anti-Tank Mines'],
// ── Robotics Workshop ─────────────────────────────────────────────────────
['Machine Gun Sentry', 'Robotics Workshop', 'Machine Gun Sentry'],
['Gatling Sentry', 'Robotics Workshop', 'Gatling Sentry'],
['Mortar Sentry', 'Robotics Workshop', 'Mortar Sentry'],
['Guard Dog', 'Robotics Workshop', 'Guard Dog'],
['Autocannon Sentry', 'Robotics Workshop', 'Autocannon Sentry'],
['Rocket Sentry', 'Robotics Workshop', 'Rocket Sentry'],
['EMS Mortar Sentry', 'Robotics Workshop', 'EMS Mortar Sentry'],
['Patriot Exosuit', 'Robotics Workshop', 'Patriot Exosuit'],
['Emancipator Exosuit', 'Robotics Workshop', 'Emancipator Exosuit'],
// ── Urban Legends / Defensive ─────────────────────────────────────────────
['Directional Shield', 'Urban Legends', 'Directional Shield'],
['Anti-Tank Emplacement', 'Urban Legends', 'Anti-Tank Emplacement'],
];
function fetchURL(url) {
return new Promise((resolve, reject) => {
const req = https.get(url, (res) => {
if (res.statusCode === 301 || res.statusCode === 302) {
return fetchURL(res.headers.location).then(resolve).catch(reject);
}
if (res.statusCode !== 200) {
reject(new Error(`HTTP ${res.statusCode} for ${url}`));
res.resume();
return;
}
const chunks = [];
res.on('data', d => chunks.push(d));
res.on('end', () => resolve(Buffer.concat(chunks)));
});
req.on('error', reject);
req.setTimeout(10000, () => { req.destroy(); reject(new Error('Timeout: ' + url)); });
});
}
async function downloadAll() {
let ok = 0, fail = 0;
const failed = [];
for (const [name, folder, file] of ICON_MAP) {
// Local output: public/icons/<slug>.svg (flat directory, slug = name)
const slug = name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
const outPath = path.join(ICONS_DIR, slug + '.svg');
if (fs.existsSync(outPath)) {
console.log(` ✓ skip ${name}`);
ok++;
continue;
}
// Build GitHub raw URL (spaces → %20)
const encoded = encodeURIComponent(folder) + '/' + encodeURIComponent(file + '.svg');
const url = `${BASE_URL}/${encoded}`;
try {
const buf = await fetchURL(url);
fs.writeFileSync(outPath, buf);
console.log(` ↓ ok ${name}`);
ok++;
} catch (err) {
console.log(` ✗ FAIL ${name} (${err.message})`);
fail++;
failed.push({ name, url });
}
// Be polite to GitHub CDN
await new Promise(r => setTimeout(r, 80));
}
console.log(`\nDone: ${ok} ok, ${fail} failed`);
if (failed.length) {
console.log('Failed:');
failed.forEach(f => console.log(` ${f.name}${f.url}`));
}
// Output slug map for server.js
const slugMap = {};
for (const [name] of ICON_MAP) {
const slug = name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
if (fs.existsSync(path.join(ICONS_DIR, slug + '.svg'))) {
slugMap[name] = '/icons/' + slug + '.svg';
}
}
const mapPath = path.join(ICONS_DIR, '_map.json');
fs.writeFileSync(mapPath, JSON.stringify(slugMap, null, 2));
console.log(`\nIcon map written to ${mapPath}`);
}
downloadAll().catch(console.error);
+75 -74
View File
@@ -18,81 +18,82 @@ const DATA_DIR = path.join(__dirname, 'data');
if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true });
// ── Stratagems (mirrored in public/stratagems.js) ─────────────────────────────
const ICON = (slug) => '/icons/' + slug + '.svg';
const STRATAGEMS = [
// Patriotic Administration Center
{ name: 'Reinforce', category: 'Patriotic Administration Center', sequence: ['up','down','right','left','up'] },
{ name: 'Resupply', category: 'Patriotic Administration Center', sequence: ['down','down','up','right'] },
{ name: 'SOS Beacon', category: 'Patriotic Administration Center', sequence: ['up','down','right','up'] },
{ name: 'Hellbomb', category: 'Patriotic Administration Center', sequence: ['down','up','left','down','up','right','down','up'] },
{ name: 'SEAF Artillery', category: 'Patriotic Administration Center', sequence: ['right','up','up','down'] },
{ name: 'Upload Data', category: 'Patriotic Administration Center', sequence: ['right','right','left','up','up'] },
{ name: 'Eagle Rearm', category: 'Patriotic Administration Center', sequence: ['up','up','left','up','right'] },
{ name: 'Prospecting Drill', category: 'Patriotic Administration Center', sequence: ['down','down','left','right','down'] },
// Orbital Cannons
{ name: 'Orbital Gatling Barrage', category: 'Orbital Cannons', sequence: ['right','down','left','up','up'] },
{ name: 'Orbital Airburst Strike', category: 'Orbital Cannons', sequence: ['right','right','right'] },
{ name: 'Orbital 120MM HE Barrage', category: 'Orbital Cannons', sequence: ['right','right','down','left','right','down'] },
{ name: 'Orbital 380MM HE Barrage', category: 'Orbital Cannons', sequence: ['right','down','up','up','left','down','down'] },
{ name: 'Orbital Walking Barrage', category: 'Orbital Cannons', sequence: ['right','down','right','down','right','down'] },
{ name: 'Orbital Laser', category: 'Orbital Cannons', sequence: ['right','down','up','right','down'] },
{ name: 'Orbital Railcannon Strike', category: 'Orbital Cannons', sequence: ['right','up','down','down','right'] },
{ name: 'Orbital Precision Strike', category: 'Orbital Cannons', sequence: ['right','right','up'] },
{ name: 'Orbital Gas Strike', category: 'Orbital Cannons', sequence: ['right','right','down','right'] },
{ name: 'Orbital EMS Strike', category: 'Orbital Cannons', sequence: ['right','right','left','down'] },
{ name: 'Orbital Smoke Strike', category: 'Orbital Cannons', sequence: ['right','right','down','up'] },
{ name: 'Orbital Illumination Flare', category: 'Orbital Cannons', sequence: ['right','right','left','left'] },
// Hangar
{ name: 'Eagle Strafing Run', category: 'Hangar', sequence: ['up','right','right'] },
{ name: 'Eagle Airstrike', category: 'Hangar', sequence: ['up','right','down','right'] },
{ name: 'Eagle Cluster Bomb', category: 'Hangar', sequence: ['up','right','down','down','right'] },
{ name: 'Eagle Napalm Airstrike', category: 'Hangar', sequence: ['up','right','down','up'] },
{ name: 'LIFT-850 Jump Pack', category: 'Hangar', sequence: ['down','up','up','down','up'] },
{ name: 'Eagle Smoke Strike', category: 'Hangar', sequence: ['up','right','up','down'] },
{ name: 'Eagle 110MM Rocket Pods', category: 'Hangar', sequence: ['up','right','up','left'] },
{ name: 'Eagle 500KG Bomb', category: 'Hangar', sequence: ['up','right','down','down','down'] },
// Bridge
{ name: 'Patriot Exosuit', category: 'Bridge', sequence: ['left','down','right','up','left','down','right'] },
{ name: 'Emancipator Exosuit', category: 'Bridge', sequence: ['left','down','right','up','left','down','down'] },
// Engineering Bay Support Weapons
{ name: 'Machine Gun', category: 'Engineering Bay', sequence: ['down','left','down','up','right'] },
{ name: 'Anti-Materiel Rifle', category: 'Engineering Bay', sequence: ['down','left','right','up','down'] },
{ name: 'Stalwart', category: 'Engineering Bay', sequence: ['down','left','down','up','up','left'] },
{ name: 'Expendable Anti-Tank', category: 'Engineering Bay', sequence: ['down','down','left','up'] },
{ name: 'Recoilless Rifle', category: 'Engineering Bay', sequence: ['down','left','right','right','left'] },
{ name: 'Flamethrower', category: 'Engineering Bay', sequence: ['down','left','up','down','up'] },
{ name: 'Autocannon', category: 'Engineering Bay', sequence: ['down','left','down','up','up','right'] },
{ name: 'Heavy Machine Gun', category: 'Engineering Bay', sequence: ['down','left','up','down','down'] },
{ name: 'Airburst Rocket Launcher', category: 'Engineering Bay', sequence: ['down','up','up','left','right'] },
{ name: 'Commando', category: 'Engineering Bay', sequence: ['down','left','up','down','right'] },
{ name: 'Railgun', category: 'Engineering Bay', sequence: ['down','right','down','up','left','right'] },
{ name: 'Spear', category: 'Engineering Bay', sequence: ['down','down','up','down','down'] },
{ name: 'Quasar Cannon', category: 'Engineering Bay', sequence: ['down','down','up','left','right'] },
{ name: 'Arc Thrower', category: 'Engineering Bay', sequence: ['down','right','down','up','left','left'] },
{ name: 'Laser Cannon', category: 'Engineering Bay', sequence: ['down','left','down','up','left'] },
{ name: 'Grenade Launcher', category: 'Engineering Bay', sequence: ['down','left','up','left','down'] },
// Engineering Bay Equipment
{ name: 'Supply Pack', category: 'Engineering Bay', sequence: ['down','left','down','up','up','down'] },
{ name: 'Guard Dog Rover', category: 'Engineering Bay', sequence: ['down','up','left','up','right','right'] },
{ name: 'Guard Dog', category: 'Engineering Bay', sequence: ['down','up','left','up','right','down'] },
{ name: 'Ballistic Shield Backpack', category: 'Engineering Bay', sequence: ['down','left','down','down','up','left'] },
{ name: 'Shield Generator Pack', category: 'Engineering Bay', sequence: ['down','up','left','right','left','right'] },
{ name: 'Directional Shield', category: 'Engineering Bay', sequence: ['down','left','up','up','right'] },
// Engineering Bay Mines
{ name: 'Anti-Personnel Minefield', category: 'Engineering Bay', sequence: ['down','left','up','right'] },
{ name: 'Incendiary Mines', category: 'Engineering Bay', sequence: ['down','left','left','down'] },
{ name: 'Anti-Tank Mines', category: 'Engineering Bay', sequence: ['down','down','left','left'] },
// Robotics Workshop
{ name: 'Machine Gun Sentry', category: 'Robotics Workshop', sequence: ['down','up','right','right','up'] },
{ name: 'Gatling Sentry', category: 'Robotics Workshop', sequence: ['down','up','right','left'] },
{ name: 'Mortar Sentry', category: 'Robotics Workshop', sequence: ['down','up','right','right','down'] },
{ name: 'Autocannon Sentry', category: 'Robotics Workshop', sequence: ['down','up','right','up','left','up'] },
{ name: 'Rocket Sentry', category: 'Robotics Workshop', sequence: ['down','up','right','right','left'] },
{ name: 'EMS Mortar Sentry', category: 'Robotics Workshop', sequence: ['down','up','right','down','right'] },
{ name: 'Tesla Tower', category: 'Robotics Workshop', sequence: ['down','up','right','up','left','up','up'] },
// Defensive
{ name: 'Shield Generator Relay', category: 'Defensive', sequence: ['down','up','left','right','left','down'] },
{ name: 'Anti-Tank Emplacement', category: 'Defensive', sequence: ['down','right','right','up','left'] },
{ name: 'Orbital Shield Generator', category: 'Defensive', sequence: ['right','right','left','down','left','down'] },
// ── Patriotic Administration Center ──────────────────────────────────────
{ name: 'Reinforce', category: 'Patriotic Administration Center', icon: ICON('reinforce'), sequence: ['up','down','right','left','up'] },
{ name: 'Resupply', category: 'Patriotic Administration Center', icon: ICON('resupply'), sequence: ['down','down','up','right'] },
{ name: 'SOS Beacon', category: 'Patriotic Administration Center', icon: ICON('sos_beacon'), sequence: ['up','down','right','up'] },
{ name: 'Hellbomb', category: 'Patriotic Administration Center', icon: ICON('hellbomb'), sequence: ['down','up','left','down','up','right','down','up'] },
{ name: 'SEAF Artillery', category: 'Patriotic Administration Center', icon: ICON('seaf_artillery'), sequence: ['right','up','up','down'] },
{ name: 'Upload Data', category: 'Patriotic Administration Center', icon: ICON('upload_data'), sequence: ['right','right','left','up','up'] },
{ name: 'Eagle Rearm', category: 'Patriotic Administration Center', icon: ICON('eagle_rearm'), sequence: ['up','up','left','up','right'] },
{ name: 'Prospecting Drill', category: 'Patriotic Administration Center', icon: ICON('prospecting_drill'), sequence: ['down','down','left','right','down'] },
// ── Orbital Cannons ───────────────────────────────────────────────────────
{ name: 'Orbital Gatling Barrage', category: 'Orbital Cannons', icon: ICON('orbital_gatling_barrage'), sequence: ['right','down','left','up','up'] },
{ name: 'Orbital Airburst Strike', category: 'Orbital Cannons', icon: ICON('orbital_airburst_strike'), sequence: ['right','right','right'] },
{ name: 'Orbital 120MM HE Barrage', category: 'Orbital Cannons', icon: ICON('orbital_120mm_he_barrage'), sequence: ['right','right','down','left','right','down'] },
{ name: 'Orbital 380MM HE Barrage', category: 'Orbital Cannons', icon: ICON('orbital_380mm_he_barrage'), sequence: ['right','down','up','up','left','down','down'] },
{ name: 'Orbital Walking Barrage', category: 'Orbital Cannons', icon: ICON('orbital_walking_barrage'), sequence: ['right','down','right','down','right','down'] },
{ name: 'Orbital Laser', category: 'Orbital Cannons', icon: ICON('orbital_laser'), sequence: ['right','down','up','right','down'] },
{ name: 'Orbital Railcannon Strike', category: 'Orbital Cannons', icon: ICON('orbital_railcannon_strike'), sequence: ['right','up','down','down','right'] },
{ name: 'Orbital Precision Strike', category: 'Orbital Cannons', icon: ICON('orbital_precision_strike'), sequence: ['right','right','up'] },
{ name: 'Orbital Gas Strike', category: 'Orbital Cannons', icon: ICON('orbital_gas_strike'), sequence: ['right','right','down','right'] },
{ name: 'Orbital EMS Strike', category: 'Orbital Cannons', icon: ICON('orbital_ems_strike'), sequence: ['right','right','left','down'] },
{ name: 'Orbital Smoke Strike', category: 'Orbital Cannons', icon: ICON('orbital_smoke_strike'), sequence: ['right','right','down','up'] },
{ name: 'Orbital Illumination Flare', category: 'Orbital Cannons', icon: ICON('orbital_illumination_flare'), sequence: ['right','right','left','left'] },
// ── Hangar ────────────────────────────────────────────────────────────────
{ name: 'Eagle Strafing Run', category: 'Hangar', icon: ICON('eagle_strafing_run'), sequence: ['up','right','right'] },
{ name: 'Eagle Airstrike', category: 'Hangar', icon: ICON('eagle_airstrike'), sequence: ['up','right','down','right'] },
{ name: 'Eagle Cluster Bomb', category: 'Hangar', icon: ICON('eagle_cluster_bomb'), sequence: ['up','right','down','down','right'] },
{ name: 'Eagle Napalm Airstrike', category: 'Hangar', icon: ICON('eagle_napalm_airstrike'), sequence: ['up','right','down','up'] },
{ name: 'LIFT-850 Jump Pack', category: 'Hangar', icon: ICON('lift_850_jump_pack'), sequence: ['down','up','up','down','up'] },
{ name: 'Eagle Smoke Strike', category: 'Hangar', icon: ICON('eagle_smoke_strike'), sequence: ['up','right','up','down'] },
{ name: 'Eagle 110MM Rocket Pods', category: 'Hangar', icon: ICON('eagle_110mm_rocket_pods'), sequence: ['up','right','up','left'] },
{ name: 'Eagle 500KG Bomb', category: 'Hangar', icon: ICON('eagle_500kg_bomb'), sequence: ['up','right','down','down','down'] },
// ── Bridge ────────────────────────────────────────────────────────────────
{ name: 'Patriot Exosuit', category: 'Bridge', icon: ICON('patriot_exosuit'), sequence: ['left','down','right','up','left','down','right'] },
{ name: 'Emancipator Exosuit', category: 'Bridge', icon: ICON('emancipator_exosuit'), sequence: ['left','down','right','up','left','down','down'] },
{ name: 'Tesla Tower', category: 'Bridge', icon: ICON('tesla_tower'), sequence: ['down','up','right','up','left','up','up'] },
{ name: 'Shield Generator Relay', category: 'Bridge', icon: ICON('shield_generator_relay'), sequence: ['down','up','left','right','left','down'] },
// ── Engineering Bay Support Weapons ────────────────────────────────────
{ name: 'Machine Gun', category: 'Engineering Bay', icon: ICON('machine_gun'), sequence: ['down','left','down','up','right'] },
{ name: 'Anti-Materiel Rifle', category: 'Engineering Bay', icon: ICON('anti_materiel_rifle'), sequence: ['down','left','right','up','down'] },
{ name: 'Stalwart', category: 'Engineering Bay', icon: ICON('stalwart'), sequence: ['down','left','down','up','up','left'] },
{ name: 'Expendable Anti-Tank', category: 'Engineering Bay', icon: ICON('expendable_anti_tank'), sequence: ['down','down','left','up'] },
{ name: 'Recoilless Rifle', category: 'Engineering Bay', icon: ICON('recoilless_rifle'), sequence: ['down','left','right','right','left'] },
{ name: 'Flamethrower', category: 'Engineering Bay', icon: ICON('flamethrower'), sequence: ['down','left','up','down','up'] },
{ name: 'Autocannon', category: 'Engineering Bay', icon: ICON('autocannon'), sequence: ['down','left','down','up','up','right'] },
{ name: 'Heavy Machine Gun', category: 'Engineering Bay', icon: ICON('heavy_machine_gun'), sequence: ['down','left','up','down','down'] },
{ name: 'Airburst Rocket Launcher', category: 'Engineering Bay', icon: ICON('airburst_rocket_launcher'), sequence: ['down','up','up','left','right'] },
{ name: 'Commando', category: 'Engineering Bay', icon: ICON('commando'), sequence: ['down','left','up','down','right'] },
{ name: 'Railgun', category: 'Engineering Bay', icon: ICON('railgun'), sequence: ['down','right','down','up','left','right'] },
{ name: 'Spear', category: 'Engineering Bay', icon: ICON('spear'), sequence: ['down','down','up','down','down'] },
{ name: 'Quasar Cannon', category: 'Engineering Bay', icon: ICON('quasar_cannon'), sequence: ['down','down','up','left','right'] },
{ name: 'Arc Thrower', category: 'Engineering Bay', icon: ICON('arc_thrower'), sequence: ['down','right','down','up','left','left'] },
{ name: 'Laser Cannon', category: 'Engineering Bay', icon: ICON('laser_cannon'), sequence: ['down','left','down','up','left'] },
{ name: 'Grenade Launcher', category: 'Engineering Bay', icon: ICON('grenade_launcher'), sequence: ['down','left','up','left','down'] },
// ── Engineering Bay Equipment ───────────────────────────────────────────
{ name: 'Supply Pack', category: 'Engineering Bay', icon: ICON('supply_pack'), sequence: ['down','left','down','up','up','down'] },
{ name: 'Guard Dog Rover', category: 'Engineering Bay', icon: ICON('guard_dog_rover'), sequence: ['down','up','left','up','right','right'] },
{ name: 'Guard Dog', category: 'Engineering Bay', icon: ICON('guard_dog'), sequence: ['down','up','left','up','right','down'] },
{ name: 'Ballistic Shield Backpack', category: 'Engineering Bay', icon: ICON('ballistic_shield_backpack'), sequence: ['down','left','down','down','up','left'] },
{ name: 'Shield Generator Pack', category: 'Engineering Bay', icon: ICON('shield_generator_pack'), sequence: ['down','up','left','right','left','right'] },
{ name: 'Directional Shield', category: 'Engineering Bay', icon: ICON('directional_shield'), sequence: ['down','left','up','up','right'] },
// ── Engineering Bay Mines ───────────────────────────────────────────────
{ name: 'Anti-Personnel Minefield', category: 'Engineering Bay', icon: ICON('anti_personnel_minefield'), sequence: ['down','left','up','right'] },
{ name: 'Incendiary Mines', category: 'Engineering Bay', icon: ICON('incendiary_mines'), sequence: ['down','left','left','down'] },
{ name: 'Anti-Tank Mines', category: 'Engineering Bay', icon: ICON('anti_tank_mines'), sequence: ['down','down','left','left'] },
// ── Robotics Workshop ─────────────────────────────────────────────────────
{ name: 'Machine Gun Sentry', category: 'Robotics Workshop', icon: ICON('machine_gun_sentry'), sequence: ['down','up','right','right','up'] },
{ name: 'Gatling Sentry', category: 'Robotics Workshop', icon: ICON('gatling_sentry'), sequence: ['down','up','right','left'] },
{ name: 'Mortar Sentry', category: 'Robotics Workshop', icon: ICON('mortar_sentry'), sequence: ['down','up','right','right','down'] },
{ name: 'Autocannon Sentry', category: 'Robotics Workshop', icon: ICON('autocannon_sentry'), sequence: ['down','up','right','up','left','up'] },
{ name: 'Rocket Sentry', category: 'Robotics Workshop', icon: ICON('rocket_sentry'), sequence: ['down','up','right','right','left'] },
{ name: 'EMS Mortar Sentry', category: 'Robotics Workshop', icon: ICON('ems_mortar_sentry'), sequence: ['down','up','right','down','right'] },
// ── Defensive ─────────────────────────────────────────────────────────────
{ name: 'Anti-Tank Emplacement', category: 'Defensive', icon: ICON('anti_tank_emplacement'), sequence: ['down','right','right','up','left'] },
{ name: 'Orbital Shield Generator', category: 'Defensive', icon: null, sequence: ['right','right','left','down','left','down'] },
];
const VALID_NAMES = new Set(STRATAGEMS.map(s => s.name));