0
TOOLS#1d77119e
Marvel Super Heroes — Sealed Win Dossier
@Owner·deposited 18h ago·updated 17h ago·14 views
TOOLS#1d77119e
Marvel Super Heroes — Sealed Win Dossier
OW
@Owner
14Views
0Comments
0Forks
0Saves
SHARE · REMIX
Marvel Super Heroes — Sealed Win Dossier — a JSX Tools widget by @Owner.
CONTROLS
mtgmarvelsealedlimiteddeckbuilder
No comments yet. Be the first!
✦ Remix with AI
SDK in this widget
- localStorage: localStorage detected. Prefer vibes.save/load for per-user persistence.
Generated prompt
You are helping me modify a vibe-coded widget from itjustvibes.com.
[VIBE CODE: "Marvel Super Heroes — Sealed Win Dossier" by @Owner]
Source: https://itjustvibes.com/Owner/marvel-super-heroes-sealed-win-dossier
Type: React/JSX
--- SOURCE CODE ---
```jsx
import { useState } from "react";
const COLS = "WUBRG";
const colorsOf = (c) => (c === "A" || c === "gold") ? [] : c.length === 2 ? c.split("") : (COLS.includes(c) ? [c] : []);
const isBomb = (o) => /Bomb|Win-con/.test(o);
const isRemoval = (o) => /[Rr]emoval|Board wipe/.test(o);
const FIX = new Set(["Stark Industries Executive", "Ant-Man's Army"]);
const isFix = (c) => /Fixing/.test(c.o) || FIX.has(c.n);
const isTrap = (c) => c.o === "Trap";
const TR = (t) => ({ S: 0, A: 1, B: 2, C: 3 }[t[0]]);
const RAR = (r) => r.split("/").map((x) => ({ M: "Mythic", R: "Rare", U: "Uncommon", C: "Common" }[x] || x)).join(" / ");
const CNAME = { W: "White", U: "Blue", B: "Black", R: "Red", G: "Green" };
const PNAME = { W: "White", U: "Blue (not Black!)", B: "Black", R: "Red", G: "Green", A: "Artifact / colorless", gold: "Multicolor" };
const ccVar = (c) => c === "A" ? "var(--art)" : (c === "gold" || c.length === 2) ? "var(--gold)" : "var(--" + c.toLowerCase() + ")";
const ld = (k, d) => { try { const v = localStorage.getItem(k); return v ? JSON.parse(v) : d; } catch (e) { return d; } };
const persist = (k, v) => { try { localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} };
const CARDS = [
{ n: "Captain Marvel, Earth's Protector", c: "W", r: "M/R", o: "Bomb", t: "S", w: "Flash flyer with lifelink that becomes indestructible — near-unbeatable if unanswered. Rated a perfect 5.0." },
{ n: "Agent Phil Coulson", c: "W", r: "R", o: "Bomb", t: "A/S", w: "Anthem and buff for your Heroes; the opponent has to answer it immediately." },
{ n: "Helicarrier Strike", c: "W", r: "C/U", o: "Removal", t: "S/A", w: "Teamwork burn that scales to 4 damage — and 4 damage kills about 89% of creatures." },
{ n: "Murdock's Crusade", c: "W", r: "U", o: "Removal", t: "A/B", w: "Exile removal (beats indestructible and recursion); better in Sealed than draft." },
{ n: "Super Villain Lockup", c: "W", r: "C/U", o: "Removal", t: "B", w: "Shuts a creature off; strong against Black/Red decks that can't remove the enchantment." },
{ n: "Web Up", c: "W", r: "C", o: "Removal", t: "A/B", w: "Draftsim's #1 white common — cheap, efficient removal that keeps the white curve moving." },
{ n: "Hero in Training", c: "W", r: "C", o: "Hero creature", t: "B", w: "Draftsim's #2 white common — a strong early Hero body for the aggressive white curve." },
{ n: "Take Up the Shield", c: "W", r: "C", o: "Combat trick", t: "B", w: "Draftsim's #3 white common — a protective combat trick; excellent in aggressive and attack-alone decks." },
{ n: "Brave Brawler", c: "W", r: "C", o: "Hero creature", t: "B/C", w: "Draftsim's #4 white common — a dependable aggressive Hero body." },
{ n: "Borough Backup", c: "W", r: "C", o: "Premium common", t: "A/B", w: "Makes token bodies and fixes mana; glue for Teamwork, Heroes, and go-wide decks." },
{ n: "Wakandan Royal Guard", c: "W", r: "C", o: "Premium common", t: "B", w: "Repeatable payoff for a Heroes deck." },
{ n: "Captain America, Super-Soldier // Wings of Freedom", c: "W", r: "R/U", o: "Threat", t: "B/A", w: "Strong Hero legend, better with synergy." },
{ n: "Captain Mar-Vell, Space-Born", c: "W", r: "R", o: "Trap", t: "C", w: "A fine curve-topper, but outclassed by cheaper, stronger five-drops." },
{ n: "Super Suit", c: "W", r: "C", o: "Trap", t: "C", w: "Tired equipment design; rarely worth a slot." },
{ n: "Kang, Temporal Tyrant", c: "BU", r: "M/R", o: "Bomb", t: "A/S", w: "The Blue/Black 'draw second card' signpost — a draw-two engine with runaway value if left unchecked." },
{ n: "Ghost, Spectral Saboteur", c: "U", r: "R/U", o: "Threat", t: "A", w: "Unblockable — carries Equipment and 'attack alone' plans; the UB hybrid signpost." },
{ n: "Frozen in Ice", c: "U", r: "C/U", o: "Removal", t: "A/B", w: "Draftsim's #3 blue common — blue's main removal: taps a creature down AND turns off its abilities." },
{ n: "Atlantis Attacks", c: "U", r: "U", o: "Removal/tempo", t: "B", w: "Bounce that can also make a hexproof attacker; closes games." },
{ n: "We Say Thee Nay!", c: "U", r: "U", o: "Removal", t: "B", w: "Draftsim's #2 blue common — a counterspell that answers bombs before they ever land." },
{ n: "Trickster's Stratagem", c: "U", r: "C/U", o: "Tempo", t: "B", w: "Buys time or pushes damage." },
{ n: "S.H.I.E.L.D. Deployment Drone", c: "U", r: "C", o: "Token-maker", t: "A/B", w: "Draftsim's #1 blue common — makes token bodies for tempo, Teamwork, and artifact count; flexible glue." },
{ n: "Roxxon Brutes", c: "U", r: "C", o: "Premium common", t: "A/B", w: "Cycling flyer — air pressure plus graveyard fuel; plays in many shells." },
{ n: "Red Room Recruit", c: "U", r: "C", o: "Premium common", t: "B", w: "Draftsim's #4 black common (a connive two-drop) — great with discard payoffs." },
{ n: "Depower", c: "U", r: "C", o: "Removal/tempo", t: "B", w: "Draftsim's #4 blue common — a tempo play that neutralizes a creature." },
{ n: "Visions of Villainy", c: "U", r: "U", o: "Card adv", t: "A/B", w: "Draftsim's #2 black common — plays like Night's Whisper with even one Villain, and Villains are everywhere." },
{ n: "Construct a Cosmic Cube", c: "U", r: "R", o: "Build-around", t: "B/A", w: "Connive engine that becomes a win condition at 7 counters." },
{ n: "Super Intelligence", c: "U", r: "C/U", o: "Trap", t: "C", w: "Does nothing until your next turn — a free two-for-one for the opponent. Cut from ~95% of decks." },
{ n: "Doctor Doom", c: "B", r: "M", o: "Bomb", t: "S", w: "Rated a perfect 5.0 — draws every turn (including the turn you cast it) and makes three indestructible bodies. First pick over almost anything." },
{ n: "Dark Deed", c: "B", r: "U", o: "Removal", t: "S", w: "Kills any creature with toughness 4 or less, at instant speed, and beats indestructible. A strict upgrade to Last Gasp." },
{ n: "Cruel Alliance", c: "B", r: "C", o: "Removal", t: "S/A", w: "Draftsim's #1 black common: ~64% kill rate normally, but unconditional and gain 2 life with Teamwork 2, all for 3 mana." },
{ n: "Hour of Defeat", c: "B", r: "C/U", o: "Removal", t: "A", w: "Draftsim's #3 black common — a fairly-priced instant-speed kill." },
{ n: "Elektra, Daughter of the Hand", c: "B", r: "R/U", o: "Removal", t: "A", w: "Her ability kills about 84% of creatures and is hard to counter." },
{ n: "Killmonger, Scourge of Wakanda", c: "BG", r: "M/R", o: "Bomb/removal", t: "A", w: "The Black/Green graveyard signpost; feeds the graveyard and interacts. High impact." },
{ n: "Madame Hydra", c: "BR", r: "U", o: "Threat engine", t: "A", w: "The Black/Red 'Villains matter' signpost; pumps out a stream of Villains." },
{ n: "Widow's Bite", c: "B", r: "C", o: "Trick/removal", t: "B", w: "Combat trick that snipes attackers or blockers." },
{ n: "Yellowjacket, Heartless Marauder", c: "B", r: "U", o: "Threat", t: "B", w: "Evasion plus lifelink — great in a race." },
{ n: "Doom Reigns Supreme", c: "B", r: "R", o: "Plan", t: "B/C", w: "Strong only in a focused, heavy-Black Villains deck; slow otherwise. (Draftsim rates it higher — a payoff if you commit.)" },
{ n: "Thor, God of Thunder", c: "R", r: "M", o: "Bomb", t: "S", w: "A 5-power flyer that replays removal from your graveyard and turns all your noncreature spells into removal. One of the set's biggest bombs." },
{ n: "Lightning Strike", c: "R", r: "C", o: "Removal", t: "S/A", w: "Draftsim's #1 red common — premium burn that kills most small and mid creatures, or goes to the face." },
{ n: "Truck Toss", c: "R", r: "C/U", o: "Removal", t: "A", w: "Flexible burn and removal with reach." },
{ n: "Avengers Disassembled", c: "R", r: "R", o: "Board wipe", t: "A", w: "The set's main sweeper; also hits nonbasic lands. A situational bomb — don't run it in your own creature-flood deck." },
{ n: "Mjolnir, Hammer of Thor", c: "R", r: "R/M", o: "Bomb equipment", t: "A/S", w: "Flexible Equipment (also an artifact) that can take over a game; rated a bomb in early Sealed pools." },
{ n: "Stark Industries Executive", c: "R", r: "C/U", o: "Premium common", t: "A", w: "Excellent in Sealed: a one-drop that fixes your mana AND is sacrifice fodder." },
{ n: "Iron Man, Master of Machines", c: "RU", r: "R", o: "Bomb", t: "A/S", w: "The Blue/Red artifacts signpost; grows fast and draws cards on attack." },
{ n: "Hulk, Gamma Goliath", c: "GR", r: "U", o: "Engine", t: "A", w: "The Red/Green power-up signpost; discounts your power-up activations for wild swings." },
{ n: "Crimson Operative", c: "R", r: "C", o: "Prowess threat", t: "B/A", w: "Draftsim's #2 red common — a prowess two-drop that grows when you cast noncreature spells; RW/aggro glue." },
{ n: "HYDRA Assault Robot", c: "R", r: "C", o: "Robot creature", t: "B", w: "Draftsim's #3 red common — a Robot body that taps for Teamwork and counts as an artifact." },
{ n: "Kree Sentinel", c: "R", r: "C", o: "Creature", t: "B/C", w: "Draftsim's #4 red common — a reliable red creature for the curve." },
{ n: "Photon Blast Barrage", c: "R", r: "C/U", o: "Removal", t: "B/A", w: "Scales with extra mana and Improvise." },
{ n: "Human Torch, Johnny Storm", c: "R", r: "R/U", o: "Threat", t: "B/A", w: "Evasive, and explosive with an early power-up." },
{ n: "Super Speed", c: "R", r: "C", o: "Trap", t: "C", w: "Mediocre trick; only in fast double-spell decks." },
{ n: "The Thing, Ben Grimm", c: "G", r: "R", o: "Bomb", t: "A", w: "Green/White top-end that scales fast and demands an answer." },
{ n: "Punishing Punch", c: "G", r: "C", o: "Removal", t: "A", w: "The best Green removal; often castable for just one mana (fight)." },
{ n: "She-Hulk, Jade Defender", c: "G", r: "U", o: "Removal", t: "B/A", w: "A Naturalize (destroy an artifact or enchantment) stapled to a creature body." },
{ n: "Doc Samson, Super Psychiatrist", c: "G", r: "R/U", o: "Ramp/engine", t: "A", w: "Mana acceleration plus counter distribution; a key enabler." },
{ n: "Undercover Skrull", c: "G", r: "C/U", o: "Fixing", t: "A/B", w: "Draftsim's #1 green common — the set's best creature mana-fixer and your splash engine." },
{ n: "Titania, Rugged Rumbler", c: "G", r: "U", o: "Threat", t: "A/B", w: "The Black/Green graveyard signpost (hybrid side); payoff for graveyard and lands." },
{ n: "Hercules, Prince of Power", c: "G", r: "R/U", o: "Threat", t: "B", w: "A power-up and counters beater." },
{ n: "Epic Fight", c: "G", r: "C/U", o: "Removal", t: "B", w: "Pumps then fights; sorcery speed makes it exploitable. (Draftsim rates it highly.)" },
{ n: "Pet Avengers", c: "G", r: "C", o: "Go-wide creature", t: "B", w: "Draftsim's #2 green common — adds board presence for go-wide and Heroes decks." },
{ n: "Serpent Specialist", c: "G", r: "C", o: "Power-up creature", t: "B", w: "Draftsim's #4 green common — a deathtouch one-drop with power-up: a cheap blocker now, a mana sink later." },
{ n: "Ant-Man's Army", c: "G", r: "C", o: "Utility", t: "B", w: "Flexible fixing and lifegain." },
{ n: "Go Nuts!", c: "G", r: "C", o: "Removal (fight)", t: "B/C", w: "Draftsim's #3 green common — a fight spell (removal) that needs a creature; solid in creature-heavy green decks." },
{ n: "Moon Girl and Devil Dinosaur", c: "GU", r: "M/R", o: "Bomb", t: "A/S", w: "Premium connive threat that wins on its own." },
{ n: "Thanos, the Mad Titan", c: "gold", r: "M/R", o: "Bomb", t: "A", w: "Three-mana deathtouch and lifelink body; the odd/even mass-wipe is gravy in uneven Sealed curves. (Draftsim is lower on him — play him as a good body, not a format-warper.)" },
{ n: "Cloak and Dagger, Entwined", c: "WB", r: "R/U", o: "Removal/disruption", t: "A", w: "Flexible removal; peeking at their hand is often the best mode." },
{ n: "Wolverine, Fierce Fighter", c: "RG", r: "R/U", o: "Removal+body", t: "A", w: "An efficient creature that also removes — pure value." },
{ n: "War Machine, Legacy of Iron", c: "RW", r: "U", o: "Threat", t: "A", w: "The Red/White signpost (hybrid side); doubles any buffs it gets, always a huge clock." },
{ n: "U.S.Agent, John Walker", c: "WB", r: "U", o: "Threat", t: "B/A", w: "The White/Black 'attack alone' signpost (hybrid side); easy to cast plus free Equipment later." },
{ n: "Captain America, Living Legend", c: "WU", r: "U", o: "Engine", t: "A", w: "The White/Blue Teamwork signpost; pseudo-vigilance for your whole team — best with tap and Teamwork." },
{ n: "Baron Strucker, HYDRA Overlord", c: "BR", r: "U", o: "Engine", t: "A", w: "Cost reduction plus connive access." },
{ n: "Avengers: Under Siege", c: "BR", r: "R", o: "Board impact", t: "B/A", w: "Buffs your side or clears blockers for a lethal turn." },
{ n: "The Coming of Galactus", c: "BG", r: "R/M", o: "Win-con", t: "B/A", w: "Snowballs out of control if it isn't answered." },
{ n: "Black Widow, Double Agent", c: "WB", r: "U", o: "WB signpost", t: "A", w: "The White/Black 'Attack Alone' signpost — rewards swinging with a single threat; the banner card for the WB deck." },
{ n: "Bullseye, Death Dealer", c: "BR", r: "U", o: "BR signpost", t: "B/A", w: "The Black/Red 'Villains Matter' signpost (hybrid side) — a payoff that pushes the BR Villains plan." },
{ n: "Black Panther, Vanguard", c: "GW", r: "U", o: "GW signpost", t: "A", w: "The Green/White 'Heroes Matter' signpost — pays you off for flooding the board with Heroes." },
{ n: "Spider-Man, To the Rescue", c: "GW", r: "U", o: "GW signpost", t: "B/A", w: "The Green/White 'Heroes' signpost (hybrid side) — flexible Hero-deck support." },
{ n: "Abomination, Terrifying Titan", c: "GR", r: "U", o: "RG signpost", t: "B/A", w: "The Red/Green 'Power-Up' signpost (hybrid side) — rewards stacking counters and power-up plays." },
{ n: "Speedball, New Warrior", c: "RU", r: "U", o: "UR signpost", t: "B", w: "The Blue/Red signpost that actually plays more like an aggressive red-white card — a flexible beater." },
{ n: "Spider-Woman, Secret Agent", c: "WU", r: "U", o: "WU signpost", t: "B", w: "The White/Blue 'Teamwork' signpost (hybrid side) — supports tapping your team for value." },
{ n: "Thor Odinson", c: "RW", r: "U", o: "RW signpost", t: "A", w: "The Red/White 'Noncreature Spells' signpost — a payoff for the aggressive spells-matter deck." },
{ n: "The Mind Stone", c: "A", r: "R/M", o: "Bomb (chase)", t: "A/S", w: "The set's headline colorless artifact; the normal printing is a strong pull. (The ~150-copy ultra-rare is Collector-only and won't be in your Play Boosters.)" },
{ n: "The Vision", c: "A", r: "R", o: "Threat", t: "A", w: "Artifact creature that can go indestructible; a Blue/Red keystone." },
{ n: "Ultron, Artificial Malevolence", c: "A", r: "R/M", o: "Threat", t: "A", w: "Builds an artifact army with a payoff." },
{ n: "Dependable Quinjet", c: "A", r: "C/U", o: "Fixing", t: "A/B", w: "Draftsim's #2 colorless common — the set's main artifact mana-fixer; enables your splashes." },
{ n: "H.E.R.B.I.E. Scout Unit", c: "A", r: "C", o: "Artifact creature", t: "A/B", w: "Draftsim's #1 colorless common — an artifact creature that slots into any deck and boosts artifact count." },
{ n: "Ultron Drone", c: "A", r: "C", o: "Artifact creature", t: "B", w: "Draftsim's #3 colorless common — a flexible artifact body for any deck (and UR artifact count)." },
{ n: "Vibranium Energy Daggers", c: "A", r: "C", o: "Equipment", t: "B", w: "Draftsim's #4 colorless common — cheap Equipment that fits in any deck." },
{ n: "A.I.M. Synthoids", c: "A", r: "C", o: "Artifact creature", t: "B/C", w: "Draftsim's #5 colorless common — a flexible artifact body and artifact-count enabler." },
{ n: "Iron Man Armor", c: "A", r: "U", o: "Support", t: "B/A", w: "Evasion that becomes a creature when you need a body." },
{ n: "Captain America's Shield", c: "A", r: "C/U", o: "Support", t: "B", w: "Adds toughness and taps a blocker; needs a creature. (Combos with Captain America — see Combos.)" },
{ n: "Allied dual land cycle", c: "A", r: "C/R", o: "Fixing land", t: "A", w: "Basically untapped two-color lands; take them early — they enable splashes." },
{ n: "Avengers Tower / Villainous Hideout", c: "A", r: "U/R", o: "Fixing land", t: "B/A", w: "Any-color mana for Heroes or Villains, plus utility." },
{ n: "Surveillance Room / Baxter Building / Castle Doom", c: "A", r: "U/R", o: "Utility land", t: "B", w: "Scry-the-top, filter-draw, or artifact support." },
];
const COMBO = [
["Mjolnir, Hammer of Thor", "Thor, God of Thunder", "Thor is a red legendary, so he's \u201CWorthy\u201D and can equip Mjolnir easily \u2014 turning the God of Thunder into a game-ending threat."],
["Mjolnir, Hammer of Thor", "The Mighty Thor, Jane Foster", "Jane Foster is also Worthy and can wield Mjolnir \u2014 another way to land the hammer on a huge body."],
["Captain America, Wings of Freedom", "Captain America's Shield", "The Shield equips and protects Cap, turning an already-strong threat into one that's very hard to deal with."],
["Hawkeye, Young Avenger", "Hawkeye's Bow", "Hawkeye's signature Equipment pairs directly with him for a focused, evasive threat."],
["Fin Fang Foom", "Avengers Disassembled", "Draftsim's recommended pairing \u2014 use the sweeper alongside Fin Fang Foom to set up a board clear that lands in your favor."],
["The Fantastic Four uncommons", "(each other)", "The Fantastic Four uncommons are designed to combine \u2014 collect them to unlock their team synergy."],
];
const ARCH = [
[1, "BW", "White + Black", "Attack Alone", "Best removal colors plus both perfect-rated bombs (Captain Marvel, Doctor Doom). Grind with evasive threats and out-remove them.", { s: "Black Widow, Double Agent; U.S.Agent, John Walker", g: "Evasive bodies + S.H.I.E.L.D. Spy Kit + Luke Cage (indestructible when attacking alone)", c: "Any unblockable or evasive creature + an Equipment that snowballs it" }],
[2, "BR", "Black + Red", "Villains Matter", "Villains are the most common creature type, so the payoffs are always live. Pressure plus burn plus Doctor Doom finishes it.", { s: "Madame Hydra; Bullseye, Death Dealer", g: "Baron Strucker, token-makers, Doom Reigns Supreme as a payoff", c: "The Masters of Evil (Villain lord) + any go-wide token-maker" }],
[3, "RW", "White + Red", "Noncreature / Aggro", "White Heroes curve plus red removal and Thor. Race them dead behind burn.", { s: "Thor Odinson; War Machine, Legacy of Iron", g: "Prowess two-drops (Crimson Operative), cheap tricks", c: "War Machine + any pump or buff (it doubles them) for instant lethal" }],
[4, "BG", "Black + Green", "Creatures in Graveyard", "Out-grind with recursion; green fixing lets you splash a bomb.", null],
[5, "BU", "Blue + Black", "Draw Second Card", "Answer everything, pull ahead on cards, and win with Kang or a bomb.", null],
[6, "GW", "Green + White", "Heroes Matter", "Flood the board with Heroes and overrun — but watch the red sweeper.", null],
[7, "UW", "White + Blue", "Teamwork", "Tempo and tap synergies, but the theme is thin — really white aggro splashing blue.", null],
[8, "GR", "Red + Green", "Power-Up", "Ramp into oversized power-up beaters; high ceiling, removal-light, inconsistent.", null],
[9, "GU", "Green + Blue", "+1/+1 Counters", "Snowball one big creature; slow and removal-light.", null],
[10, "RU", "Blue + Red", "Artifacts", "Wants an artifact critical mass you can't reliably open in six packs — the weakest in Sealed.", null],
];
const MECH = [
["Power-up", "An ability you activate once per creature. It adds +1/+1 counter(s) and usually a bonus. If you activate it the same turn the creature enters, the cost drops by the creature's mana cost (colored pips included).", "Your flexible curve slot — a cheap body now, or a same-turn explosive play later. Don't count it twice on your curve. Red and green have the most. Blinking or recasting the creature resets the once-per-creature use."],
["Teamwork", "An optional extra cost on some instants and sorceries (12 of them): tap any number of creatures whose total power adds up to a number, for a bonus effect — a kicker you pay with power.", "Don't build a whole Teamwork deck. Just take Teamwork removal (Cruel Alliance, Helicarrier Strike). Enable it with vigilance creatures and token-makers so tapping doesn't cost you a blocker, and never tap your team into open removal or counter mana."],
["Connive", "Draw a card, then discard a card. If you discarded a nonland, the creature gets a +1/+1 counter. It appears on blue and black cards.", "Fixes your draws, grows creatures, and fills the graveyard. It counts as 'drawing,' so it powers Blue/Black draw-two payoffs — do it at instant speed on their turn. Pitch lands when you're flooded."],
["Plans", "An enchantment type (seven cards) that gathers plan counters as you do a specific action, then fires a big payoff at a threshold and sacrifices itself. Each color has one uncommon plan, plus two rares.", "Slow build-arounds for grindy decks. Run one or two with real payoffs; don't clog your deck with enchantments that do nothing the turn you cast them."],
["Tokens", "Free permanents your cards make: Hero (White/Green), Villain (Black/Red, the most common creature type — 69 in the set), Robot or artifact (Blue/Red), Treasure (ramp + fixing + counts as an artifact), and Clue (card advantage + counts as an artifact).", "Token-makers do triple duty: bodies to tap, fuel for go-wide payoffs, and artifact count. Borough Backup and S.H.I.E.L.D. Deployment Drone are flexible glue."],
["Equipment & Auras", "Cards that buff a single creature — they need creatures on board to matter. Mjolnir uses a new 'equip worthy' rule: a red or white non-villain legendary equips it cheaply.", "For every support card (Equipment, Aura, or Teamwork spell), run two to three creatures that benefit. Prefer Equipment over Auras, since Auras get two-for-one'd when your creature dies in response."],
["Also in the set", "Improvise (tap artifacts for generic mana — Blue/Red glue), five transforming double-faced mythics (Monica Rambeau // Photon is the best), The Mind Stone's 'harness' flicker mode, and Arcane (pure flavor text here).", "Read the reminder text on the card at the table — these are situational and rarely change your color choice."],
];
const STEPS = [
["Sort and identify", "Sort your pool by color. In each color, make four piles: Bombs (rares and mythics that win alone), Removal, Evasive or efficient threats, and Filler. Star anything graded S or A. (At home, paste the pool into sealeddeck.tech for a clean view.)"],
["Pick your two colors", "For each color, count two numbers: how many bombs and threats, and how much removal you opened. Pick the two colors with the highest combined total — let your bombs and removal pick your colors, not your favorite heroes. Tie-break toward White, Black, or Red. The My Pool tab does this math for you."],
["Fill the curve and hit removal", "Build to the curve (seven to eight two-drops is the anchor). Aim for about 15 to 17 creatures (token-makers count) and about six to eight removal or interaction spells. Power-up creatures can flex up your top end, so you can run a slightly leaner five-plus slot."],
["Cut down to 23 spells", "Trim in this order: situational combat tricks, then narrow synergy cards with no payoff in your deck, then extra five-plus drops beyond your two or three, then vanilla small creatures with no evasion or ability, then Auras. Never cut removal, bombs, or your two-drop count."],
["Mulligan and sequence to win", "Keep hands with two to four lands, an early play, and a way to use your mana. Lead with a B-grade card to bait their removal before you deploy your S-grade bomb. Save the same-turn power-up explosion for when you're behind."],
];
const MULL = [
"Keep hands with two to four lands, at least one early play, and a way to use your mana. Be wary of one-land hands and all-five-drop hands.",
"Power-up: playing the cheap body on curve is often right. Save the same-turn explosion for when you're behind on board.",
"Teamwork: hold it for safe spots and use vigilance creatures or tokens so tapping doesn't open you up. Don't tap into untapped removal or counter mana.",
"Connive at instant speed when you have draw-two payoffs; pitch lands when flooded.",
"Lead with a B-grade card to bait their removal before you deploy your S-grade bomb.",
];
const SIDE = [
["Versus Aggro", "Bring in cheap removal, lifegain (Take Up the Shield, Yellowjacket), and bigger blockers. Cut slow Plans and clunky top-end."],
["Versus go-wide tokens", "Bring in sweepers (Avengers Disassembled), flyers, and ground stallers. Cut narrow one-for-ones that trade down."],
["Versus Control / Connive", "Bring in counters (We Say Thee Nay!), evasion, and hand disruption (Cloak and Dagger). Cut reactive removal with no target and add proactive threats."],
];
const TMPL = [
{ name: "Aggressive — White + Red Heroes Tempo", cc: "var(--r)", play: "Curve out with evasive Heroes, point burn at their blockers and face, and close before they untap and stabilize.", rows: [["1-drops", "2", "Agent Maria Hill, Stark Industries Executive"], ["2-drop bodies", "8", "Crimson Operative, Brave Brawler, Wakandan Royal Guard, Borough Backup, evasive Heroes"], ["3-drops", "5", "War Machine, Thor Odinson, mid Heroes"], ["4-drops", "3", "Captain America legend, a flyer finisher"], ["Top end", "1-2", "Captain Marvel or Thor, God of Thunder"], ["Removal / burn", "5-6", "Lightning Strike, Truck Toss, Helicarrier Strike, Photon Blast Barrage"]] },
{ name: "Midrange — Black + Green Graveyard (splash-friendly)", cc: "var(--g)", play: "Trade early, grind card and graveyard value, then deploy bombs they can't match. Green fixing lets you splash your single best off-color bomb.", rows: [["Fixing 1-drops", "1-2", "Undercover Skrull"], ["2-drops", "7", "Roxxon Brutes, Red Room Recruit, Doc Samson, value bodies"], ["3-drops", "5-6", "Killmonger, Elektra, mid threats"], ["4-drops", "3-4", "Titania, a bomb"], ["Top end", "2", "The Coming of Galactus (plus your splashed bomb)"], ["Removal", "6", "Dark Deed, Cruel Alliance, Hour of Defeat, Punishing Punch, She-Hulk, Widow's Bite"]] },
{ name: "Control — Blue + Black Draw-Two", cc: "var(--u)", play: "Answer every threat one-for-one, bury them in cards with connive and draw-two, and win with a single bomb or a maxed-out Cosmic Cube.", rows: [["Early bodies / connive", "7-8", "Agent Maria Hill, Roxxon Brutes, Red Room Recruit, blockers"], ["3-drops", "5", "Kang, M.O.D.O.K., value"], ["4-drops", "3", "a bomb"], ["Top end", "2-3", "Construct a Cosmic Cube, Doctor Doom, a finisher"], ["Interaction", "8-9", "Dark Deed, Cruel Alliance, Hour of Defeat, Frozen in Ice, Atlantis Attacks, We Say Thee Nay!, Visions of Villainy"]] },
];
const KEY = [
["Mana colors (this one trips people up most)", [["W", "White"], ["U", "Blue — NOT Black. In Magic the blue mana symbol is the letter U."], ["B", "Black"], ["R", "Red"], ["G", "Green"], ["Gold / multicolor", "A card that needs two colors to cast."], ["Colorless / Artifact", "Has no color — fits in any deck."], ["W/B, U/B, G/W", "The slash just joins two colors. W/B means White + Black, U/B means Blue + Black, and so on."]]],
["Rarity letters", [["C", "Common"], ["U", "Uncommon — yes, in a rarity U means Uncommon; only in mana does U mean Blue."], ["R", "Rare"], ["M", "Mythic Rare (the rarest)"]]],
["Pick grades (mine)", [["S", "First-pick bomb or premium removal — play it and build around it."], ["A", "Strong; build toward it."], ["B", "Solid playable."], ["C", "Filler or situational."], ["TRAP", "A card that looks good but usually loses you the game — leave it in the box."]]],
["Deck-building words", [["Mana value / cc / X-drop", "What a card costs to cast. A 2-drop costs 2 mana."], ["Curve", "Your spread of casting costs — you want lots of cheap plays and few expensive ones."], ["Bomb", "A card so powerful it can win the game by itself if it isn't answered."], ["Removal", "A spell that kills or neutralizes an opponent's creature."], ["Sweeper / board wipe", "Removal that hits many creatures at once."], ["Signpost", "An uncommon that points you toward a specific two-color deck (each pair has two)."], ["Tempo", "Staying ahead on board so the opponent is always reacting to you."], ["Two-for-one", "Trading one of your cards for two of theirs (good) — or the reverse (bad)."], ["Splash", "Adding a small amount of a third color just for one or two great cards."], ["Fixing", "Lands or cards that give you the colors you need."], ["Anthem", "An effect that buffs your whole team at once."]]],
["Combat keywords", [["Evasion", "Hard to block (flying, unblockable, and so on)."], ["Flying", "Can only be blocked by creatures with flying or reach."], ["Vigilance", "Doesn't tap when it attacks, so it can still block."], ["Lifelink", "You gain life equal to the damage it deals."], ["Deathtouch", "Any amount of damage it deals is enough to kill."], ["Hexproof", "Your opponent's spells can't target it."], ["Indestructible", "Can't be destroyed by damage or destroy effects (exile and -X/-X still work)."], ["Prowess", "Gets +1/+1 until end of turn whenever you cast a noncreature spell."]]],
["Set-specific words", [["Power-up", "Pay a cost once to add +1/+1 counters and a bonus; cheaper if done the turn the creature lands."], ["Teamwork N", "Tap creatures with total power N or more for a bonus on a spell."], ["Connive", "Draw then discard; a nonland discard adds a +1/+1 counter."], ["Worthy", "A red or white non-villain legendary — can equip Mjolnir cheaply."], ["Hero / Villain", "The two main creature factions; Villains are the most common type."]]],
["Source shorthand", [["WotC", "Wizards of the Coast — the company that makes Magic."], ["LSV", "Luis Scott-Vargas — a pro player and set reviewer."], ["GIH WR", "Games-in-Hand Win Rate: how often you win games in which you drew the card. Real data — not out yet."], ["ALSA", "Average Last Seen At: how late a card tends to be taken in draft. Not out yet."], ["17Lands", "The site that publishes those win-rate numbers once the set is on Arena (around June 25)."]]],
];
const CT = { 1: [1, 2], 2: [7, 8], 3: [5, 6], 4: [3, 4], 5: [2, 3], 6: [0, 1] };
const SLOTLAB = { 1: "1-drops", 2: "2-drops", 3: "3-drops", 4: "4-drops", 5: "5-drops", 6: "6+ drops" };
const CSS = `
*{box-sizing:border-box}
.msh{--bg:#0b0d13;--bg2:#12151f;--bg3:#1b1f2c;--ink:#eff2f8;--ink2:#a6afbf;--ink3:#6b7384;--line:#262b3a;--red:#e62429;--gold:#f4b223;--w:#ecd9a3;--u:#3f93d8;--b:#a86fe0;--r:#f1564c;--g:#37ab61;--art:#aab4c6;background:var(--bg);color:var(--ink);min-height:100vh;font:16px/1.55 'Barlow',system-ui,sans-serif;-webkit-font-smoothing:antialiased}
.msh ::selection{background:var(--red);color:#fff}
.msh :focus-visible{outline:2px solid var(--u);outline-offset:2px}
h1,h2,h3{font-family:'Oswald',sans-serif;letter-spacing:.02em;margin:0}
.hd{background:linear-gradient(180deg,#0e1119,#0b0d13);border-bottom:1px solid var(--line)}
.hd-stripe{height:5px;background:repeating-linear-gradient(45deg,var(--red) 0 14px,#15171f 14px 28px)}
.hd-row{display:flex;align-items:center;gap:14px;max-width:1120px;margin:0 auto;padding:14px 16px;position:relative;overflow:hidden}
.hd-row::after{content:"";position:absolute;inset:0;pointer-events:none;background-image:radial-gradient(rgba(255,255,255,.05) 1px,transparent 1.5px);background-size:7px 7px;opacity:.55}
.hd-badge{font-family:'Oswald';font-weight:700;font-size:19px;background:var(--red);color:#fff;width:46px;height:46px;display:flex;align-items:center;justify-content:center;border:2px solid rgba(255,255,255,.25);transform:skewX(-7deg);flex:none;box-shadow:3px 3px 0 rgba(0,0,0,.45);position:relative;z-index:1}
.hd-title{font-family:'Oswald';font-weight:700;font-size:clamp(20px,4.4vw,30px);line-height:1;text-transform:uppercase;position:relative;z-index:1}
.hd-sub{font-family:'Space Mono',monospace;font-size:10.5px;letter-spacing:.18em;color:var(--ink2);text-transform:uppercase;margin-top:4px;position:relative;z-index:1}
.hd-stamp{margin-left:auto;font-family:'Oswald';font-weight:600;font-size:12px;letter-spacing:.1em;color:var(--red);border:2px solid var(--red);padding:5px 9px;transform:rotate(-4deg);border-radius:3px;text-transform:uppercase;white-space:nowrap;position:relative;z-index:1}
.stick{position:sticky;top:0;z-index:30}
.tabs{display:flex;gap:2px;overflow-x:auto;background:var(--bg2);border-bottom:1px solid var(--line);padding:0 8px;scrollbar-width:none}
.tabs::-webkit-scrollbar{display:none}
.tab{font-family:'Oswald';font-weight:600;font-size:13px;letter-spacing:.05em;text-transform:uppercase;color:var(--ink2);background:none;border:0;border-bottom:3px solid transparent;padding:12px 13px;cursor:pointer;white-space:nowrap}
.tab:hover{color:var(--ink)}
.tab.on{color:var(--ink);border-bottom-color:var(--red)}
.hud{width:100%;display:flex;gap:14px;align-items:center;flex-wrap:wrap;background:#0e131d;border:0;border-bottom:1px solid var(--line);border-left:4px solid var(--gold);color:var(--ink2);padding:9px 16px;cursor:pointer;text-align:left;font-family:'Space Mono',monospace;font-size:12.5px;letter-spacing:.02em}
.hud b{color:var(--ink)}
.hud .deploy{color:var(--gold);font-weight:700}
.hud .go{margin-left:auto;color:var(--ink3);font-size:11px;white-space:nowrap}
.wrap{max-width:1120px;margin:0 auto;padding:18px 16px 48px}
.eyebrow{font-family:'Space Mono',monospace;font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--red);display:flex;align-items:center;gap:8px;margin:30px 0 10px}
.eyebrow::before{content:"";width:22px;height:2px;background:var(--red)}
.eyebrow.first{margin-top:6px}
.h2{font-size:clamp(20px,3.5vw,26px);text-transform:uppercase;margin-bottom:10px;line-height:1.1}
.lead{color:var(--ink2);max-width:72ch;margin-bottom:6px}
.panel{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:16px}
.grid{display:grid;gap:12px}
@media(min-width:720px){.g2{grid-template-columns:1fr 1fr}.g3{grid-template-columns:1fr 1fr 1fr}}
.order{display:flex;gap:14px;padding:14px 0;border-top:1px solid var(--line)}
.order:first-child{border-top:0}
.order-n{font-family:'Oswald';font-weight:700;font-size:26px;color:var(--gold);line-height:1;min-width:30px}
.order h3{font-size:17px;text-transform:uppercase;margin-bottom:4px}
.order p{color:var(--ink2);font-size:14.5px}
.call{border-left:4px solid var(--gold);background:#16140f;padding:12px 15px;border-radius:0 8px 8px 0;font-size:14px;color:var(--ink2);margin:6px 0}
.call.red{border-color:var(--red);background:#17110f}
.call b{color:var(--ink)}
.legend{display:flex;flex-wrap:wrap;gap:14px}
.lg{display:flex;align-items:center;gap:7px;font-size:13.5px;color:var(--ink2)}
.cpow{background:var(--bg2);border:1px solid var(--line);border-left:4px solid var(--cc);border-radius:8px;padding:12px 14px}
.cpow h3{font-size:15px;text-transform:uppercase;margin-bottom:3px;display:flex;align-items:center;gap:8px}
.cpow p{font-size:13.5px;color:var(--ink2)}
.btn{font-family:'Oswald';font-weight:600;font-size:13px;letter-spacing:.05em;text-transform:uppercase;background:var(--red);color:#fff;border:0;border-radius:7px;padding:10px 16px;cursor:pointer;margin-top:8px}
.btn.ghost{background:var(--bg3);color:var(--ink);border:1px solid var(--line)}
.filt{display:flex;flex-direction:column;gap:9px;margin:8px 0 16px}
.frow{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.flab{font-family:'Space Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink3);min-width:54px}
.fbtn{font-family:'Space Mono',monospace;font-size:12px;background:var(--bg3);color:var(--ink2);border:1px solid var(--line);padding:6px 10px;border-radius:6px;cursor:pointer}
.fbtn:hover{color:var(--ink)}
.fbtn.on{background:var(--red);border-color:var(--red);color:#fff}
.search{flex:1;min-width:150px;background:var(--bg3);border:1px solid var(--line);border-radius:6px;color:var(--ink);padding:8px 11px;font:14px 'Barlow',sans-serif;outline:none}
.search:focus{border-color:var(--u)}
.count{font-family:'Space Mono',monospace;font-size:12px;color:var(--ink3);margin-left:auto}
.cards{display:grid;gap:10px}
@media(min-width:680px){.cards{grid-template-columns:1fr 1fr}}
@media(min-width:1000px){.cards{grid-template-columns:1fr 1fr 1fr}}
.card{position:relative;background:var(--bg2);border:1px solid var(--line);border-left:4px solid var(--cc,var(--art));border-radius:8px;padding:11px 12px 12px;display:flex;flex-direction:column}
.card.inpool{box-shadow:inset 0 0 0 1.5px var(--g);background:#0f1611}
.ctop{display:flex;align-items:flex-start;gap:8px}
.cname{font-family:'Oswald';font-weight:600;font-size:15px;line-height:1.15;flex:1;text-transform:uppercase}
.cmeta{display:flex;flex-wrap:wrap;gap:5px;margin:8px 0 7px}
.tag{font-family:'Space Mono',monospace;font-size:10px;letter-spacing:.02em;background:var(--bg3);color:var(--ink2);border:1px solid var(--line);padding:2px 7px;border-radius:4px;text-transform:uppercase}
.tag.trap{background:#2a0f10;border-color:var(--red);color:#ff9b9b}
.cwhy{font-size:13.5px;color:var(--ink2);line-height:1.5;flex:1}
.pbtn{margin-top:11px;width:100%;font-family:'Oswald';font-weight:600;font-size:12.5px;letter-spacing:.05em;text-transform:uppercase;background:var(--bg3);color:var(--ink);border:1px solid var(--line);border-radius:6px;padding:8px;cursor:pointer}
.pbtn:hover{border-color:var(--ink3)}
.pbtn.on{background:var(--g);border-color:var(--g);color:#06210f}
.bdg{font-family:'Oswald';font-weight:700;font-size:13px;min-width:30px;text-align:center;padding:2px 6px;border-radius:5px;flex:none}
.bS{background:var(--gold);color:#241a02;box-shadow:0 0 9px rgba(244,178,35,.4)}
.bA{background:#143047;color:#7cc4ff;border:1px solid #2f74ad}
.bB{background:#241c12;color:#d2a36a;border:1px solid #6b4f2e}
.bC{background:#1c2030;color:#8a93a6;border:1px solid #333a4d}
.pips{display:flex;gap:3px;flex:none}
.pip{width:18px;height:18px;border-radius:50%;font-family:'Oswald';font-weight:700;font-size:11px;display:flex;align-items:center;justify-content:center;border:1px solid rgba(0,0,0,.35)}
.pip.W{background:var(--w);color:#5a4a1e}.pip.U{background:var(--u);color:#04203a}.pip.B{background:var(--b);color:#2a1248}.pip.R{background:var(--r);color:#3a0a08}.pip.G{background:var(--g);color:#06280f}.pip.A{background:var(--art);color:#1a2230}.pip.gold{background:linear-gradient(135deg,var(--gold),#d98a1f);color:#3a2702}
.ptab{width:100%;border-collapse:collapse;font-size:14px}
.ptab th,.ptab td{text-align:left;padding:9px 10px;border-bottom:1px solid var(--line)}
.ptab th{font-family:'Space Mono',monospace;font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink3)}
.ptab td.num,.ptab th.num{text-align:center;font-family:'Space Mono',monospace}
.ptab tr.top td{background:#11160f}
.ptab tr.top td:first-child{box-shadow:inset 3px 0 0 var(--g)}
.ptab .sc{color:var(--gold)}
.curve{display:grid;gap:8px}
.crow{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.clab{font-family:'Oswald';font-weight:600;font-size:13px;min-width:88px;text-transform:uppercase}
.step{display:flex;align-items:center;gap:8px}
.sbtn{width:30px;height:30px;border-radius:6px;background:var(--bg3);border:1px solid var(--line);color:var(--ink);font-size:18px;cursor:pointer;line-height:0}
.sbtn:hover{border-color:var(--ink3)}
.sval{font-family:'Space Mono',monospace;font-size:16px;min-width:26px;text-align:center}
.ctgt{font-family:'Space Mono',monospace;font-size:12px;color:var(--ink3)}
.dot{width:9px;height:9px;border-radius:50%;display:inline-block;margin-right:5px;vertical-align:middle}
.ok{background:var(--g)}.lo{background:var(--gold)}.hi{background:var(--red)}
.stat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:9px;margin:4px 0}
.stat{background:var(--bg2);border:1px solid var(--line);border-radius:8px;padding:11px 12px;text-align:center}
.stat .v{font-family:'Oswald';font-weight:700;font-size:26px;line-height:1}
.stat .k{font-family:'Space Mono',monospace;font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink3);margin-top:3px}
.deploybox{background:linear-gradient(180deg,#181410,#12100c);border:1px solid #5a4413;border-left:5px solid var(--gold);border-radius:10px;padding:16px;margin:6px 0}
.deploybox .dh{font-family:'Space Mono',monospace;font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold)}
.deploybox .dt{font-family:'Oswald';font-weight:700;font-size:clamp(22px,5vw,30px);text-transform:uppercase;margin:6px 0;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.deploybox .ds{color:var(--ink2);font-size:14px}
.deploybox .ds b{color:var(--ink)}
.empty{text-align:center;color:var(--ink2);padding:26px 14px;border:1px dashed var(--line);border-radius:10px}
.arow{display:flex;gap:13px;align-items:flex-start;background:var(--bg2);border:1px solid var(--line);border-radius:9px;padding:13px;margin-bottom:8px}
.arank{font-family:'Oswald';font-weight:700;font-size:27px;min-width:36px;text-align:center;line-height:1}
.r1{color:var(--gold)}.r2{color:#cfd6e2}.r3{color:#d59a5a}
.aname{font-family:'Oswald';font-weight:600;font-size:17px;text-transform:uppercase;line-height:1.1}
.apair{font-family:'Space Mono',monospace;font-size:10.5px;letter-spacing:.06em;color:var(--ink3);margin-top:2px}
.adesc{color:var(--ink2);font-size:14px;margin-top:5px}
.adetail{margin-top:9px;padding-top:9px;border-top:1px dashed var(--line);font-size:13px;color:var(--ink2);display:grid;gap:3px}
.adetail b{color:var(--ink);font-family:'Space Mono',monospace;font-size:10.5px;letter-spacing:.06em;text-transform:uppercase}
.mech{background:var(--bg2);border:1px solid var(--line);border-radius:9px;padding:15px;margin-bottom:10px}
.mech h3{font-size:17px;text-transform:uppercase;margin-bottom:6px;color:var(--ink)}
.mech .plain{font-size:14px;color:var(--ink);margin-bottom:8px}
.mech .imp{font-size:13.5px;color:var(--ink2);border-left:3px solid var(--g);padding-left:11px}
.mech .imp b{font-family:'Space Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--g);display:block;margin-bottom:2px}
.stepitem{display:flex;gap:13px;background:var(--bg2);border:1px solid var(--line);border-radius:9px;padding:14px;cursor:pointer;align-items:flex-start;margin-bottom:9px}
.stepitem.done{opacity:.6;background:#0f1611;border-color:#1f3a26}
.chk{width:26px;height:26px;border-radius:6px;border:2px solid var(--ink3);flex:none;display:flex;align-items:center;justify-content:center;font-size:15px;color:transparent}
.stepitem.done .chk{border-color:var(--g);background:var(--g);color:#06210f}
.stepitem h3{font-size:16px;text-transform:uppercase;margin-bottom:3px}
.stepitem p{color:var(--ink2);font-size:14px}
.stepitem .sn{font-family:'Space Mono',monospace;color:var(--red);font-size:11px;font-weight:700;display:block;margin-bottom:2px;letter-spacing:.1em}
.ul{list-style:none;padding:0;margin:0}
.ul li{padding:9px 0 9px 20px;border-bottom:1px solid var(--line);position:relative;color:var(--ink2);font-size:14px}
.ul li:last-child{border-bottom:0}
.ul li::before{content:"\\25B8";position:absolute;left:0;color:var(--red)}
.ul li b{color:var(--ink)}
.tmpl{background:var(--bg2);border:1px solid var(--line);border-radius:10px;overflow:hidden;margin-bottom:14px}
.tmpl-h{padding:13px 15px;border-bottom:1px solid var(--line);border-left:5px solid var(--cc)}
.tmpl-h h3{font-size:17px;text-transform:uppercase}
.tmpl-h .play{font-size:13.5px;color:var(--ink2);margin-top:5px}
.slot{display:flex;gap:10px;padding:9px 15px;border-bottom:1px solid var(--line);font-size:13.5px}
.slot:last-child{border-bottom:0}
.slot .role{font-family:'Oswald';font-weight:600;text-transform:uppercase;min-width:108px;font-size:13px}
.slot .cnt{font-family:'Space Mono',monospace;color:var(--gold);min-width:38px}
.slot .ex{color:var(--ink2);flex:1}
.land{font-family:'Space Mono',monospace;font-size:12px;color:var(--ink3);padding:9px 15px;background:#0e131d}
.kg dt{font-family:'Oswald';font-weight:600;font-size:15px;text-transform:uppercase;color:var(--ink);margin-top:18px;border-bottom:1px solid var(--line);padding-bottom:5px}
.kg dd{margin:7px 0 0;color:var(--ink2);font-size:14px;display:flex;gap:10px}
.kg dd .k{font-family:'Space Mono',monospace;color:var(--gold);min-width:120px;flex:none}
.combo{background:var(--bg2);border:1px solid var(--line);border-left:4px solid var(--gold);border-radius:8px;padding:12px 14px;margin-bottom:9px}
.combo .cpair{font-family:'Oswald',sans-serif;font-weight:600;font-size:15px;text-transform:uppercase;display:flex;flex-wrap:wrap;gap:7px;align-items:center;margin-bottom:4px}
.combo .plus{color:var(--gold)}
.combo p{font-size:13.5px;color:var(--ink2)}
.slhead{display:flex;align-items:baseline;gap:8px;font-family:'Oswald',sans-serif;font-weight:600;text-transform:uppercase;font-size:14px;margin:16px 0 7px;color:var(--ink)}
.slhead .n{font-family:'Space Mono',monospace;font-size:10.5px;letter-spacing:.04em;color:var(--ink3);text-transform:none}
.slhead.gold{color:var(--gold)}
.slhead.red{color:var(--r)}
.slhead.dim{color:var(--ink3)}
.slrow{display:flex;align-items:center;gap:9px;padding:7px 10px;background:var(--bg2);border:1px solid var(--line);border-left:3px solid var(--cc,var(--art));border-radius:6px;margin-bottom:5px}
.slrow .nm{font-family:'Oswald',sans-serif;font-weight:500;font-size:13.5px;text-transform:uppercase;flex:1;line-height:1.15}
.slrow .ro{font-family:'Space Mono',monospace;font-size:9.5px;letter-spacing:.03em;color:var(--ink3);white-space:nowrap;text-transform:uppercase}
.ft{border-top:1px solid var(--line);background:var(--bg2);color:var(--ink3);font-size:12px;padding:18px 16px;text-align:center;line-height:1.7}
.ft b{color:var(--ink2)}
`;
function Pips({ c }) {
const cs = c === "gold" ? ["gold"] : c === "A" ? ["A"] : c.length === 2 ? c.split("") : [c];
return <span className="pips">{cs.map((x, i) => <span key={i} className={"pip " + x} title={PNAME[x]}>{x === "gold" ? "\u2605" : x === "A" ? "\u25C6" : x}</span>)}</span>;
}
function Bdg({ t }) { return <span className={"bdg b" + t[0]} title={"Grade " + t}>{t}</span>; }
function SlList({ label, note, cards, accent }) {
if (!cards.length) return null;
return (<div>
<div className={"slhead" + (accent ? " " + accent : "")}>{label} <span className="n">{cards.length}{note ? " \u00B7 " + note : ""}</span></div>
{cards.map((c) => (
<div key={c.n} className="slrow" style={{ "--cc": ccVar(c.c) }}>
<Bdg t={c.t} /><span className="nm">{c.n}</span><span className="ro">{c.o}</span>
</div>
))}
</div>);
}
export default function App() {
const [tab, setTab] = useState("play");
const [pool, setPool] = useState(() => ld("msh_pool_v1", []));
const [curve, setCurve] = useState(() => ld("msh_curve_v1", { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, L: 17 }));
const [done, setDone] = useState(() => ld("msh_steps_v1", []));
const [fC, setFC] = useState("all");
const [fT, setFT] = useState("all");
const [fR, setFR] = useState("all");
const [q, setQ] = useState("");
const togglePool = (n) => setPool((p) => { const x = p.includes(n) ? p.filter((y) => y !== n) : [...p, n]; persist("msh_pool_v1", x); return x; });
const clearPool = () => { setPool([]); persist("msh_pool_v1", []); };
const setC = (k, d) => setCurve((v) => { const x = { ...v, [k]: Math.max(0, (v[k] || 0) + d) }; persist("msh_curve_v1", x); return x; });
const toggleStep = (i) => setDone((d) => { const x = d.includes(i) ? d.filter((y) => y !== i) : [...d, i]; persist("msh_steps_v1", x); return x; });
const poolCards = CARDS.filter((c) => pool.includes(c.n));
const bombTot = poolCards.filter((c) => !isTrap(c) && isBomb(c.o)).length;
const remTot = poolCards.filter((c) => !isTrap(c) && isRemoval(c.o)).length;
const stat = {};
COLS.split("").forEach((X) => {
const cx = poolCards.filter((c) => !isTrap(c) && colorsOf(c.c).includes(X));
const bombs = cx.filter((c) => isBomb(c.o)).length;
const rem = cx.filter((c) => isRemoval(c.o)).length;
const keyc = cx.filter((c) => isBomb(c.o) || isRemoval(c.o)).length;
stat[X] = { bombs, rem, play: cx.length, score: bombs * 3 + rem * 2 + (cx.length - keyc) * 0.6 };
});
const ranked = Object.entries(stat).filter(([, v]) => v.play > 0).sort((a, b) => b[1].score - a[1].score);
const rec = ranked.slice(0, 2).map((x) => x[0]);
const pairKey = [...rec].sort().join("");
const arch = ARCH.find((a) => a[1] === pairKey);
const flex = poolCards.filter((c) => !isTrap(c) && isBomb(c.o) && (c.c === "A" || c.c === "gold"));
const offBombs = poolCards.filter((c) => !isTrap(c) && isBomb(c.o) && colorsOf(c.c).length > 0 && !colorsOf(c.c).every((x) => rec.includes(x)));
const fixers = poolCards.filter((c) => isFix(c));
const byGrade = (a, b) => TR(a.t) - TR(b.t) || a.n.localeCompare(b.n);
const inColors = (c) => (c.c === "A" || c.c === "gold") ? true : (colorsOf(c.c).length > 0 && colorsOf(c.c).every((x) => rec.includes(x)));
const slPlay = poolCards.filter((c) => !isTrap(c) && inColors(c));
const slBombs = slPlay.filter((c) => isBomb(c.o)).sort(byGrade);
const slRem = slPlay.filter((c) => !isBomb(c.o) && isRemoval(c.o)).sort(byGrade);
const slLandList = slPlay.filter((c) => !isBomb(c.o) && !isRemoval(c.o) && /land/i.test(c.o)).sort(byGrade);
const slBodies = slPlay.filter((c) => !isBomb(c.o) && !isRemoval(c.o) && !/land/i.test(c.o)).sort(byGrade);
const slCut = poolCards.filter((c) => !isTrap(c) && !inColors(c) && !isBomb(c.o)).sort(byGrade);
const slTrap = poolCards.filter((c) => isTrap(c));
const slSpellN = slBombs.length + slRem.length + slBodies.length;
const totalSpells = [1, 2, 3, 4, 5, 6].reduce((s, k) => s + (curve[k] || 0), 0);
const TABS = [["play", "Playbook"], ["cards", "Cards"], ["pool", "My Pool"], ["arch", "Archetypes"], ["mech", "Mechanics"], ["check", "Build Steps"], ["temp", "Decklists"], ["key", "Key / Glossary"]];
let list = CARDS.filter((c) => {
if (fC !== "all") {
if (fC === "multi") { if (!(c.c === "gold" || c.c.length === 2)) return false; }
else if (fC === "A") { if (c.c !== "A") return false; }
else if (!colorsOf(c.c).includes(fC)) return false;
}
if (fT !== "all" && c.t[0] !== fT) return false;
if (fR === "bomb" && !isBomb(c.o)) return false;
if (fR === "rem" && !isRemoval(c.o)) return false;
if (fR === "common" && !c.r.split("/").includes("C")) return false;
if (fR === "trap" && !isTrap(c)) return false;
if (q && !(c.n + " " + c.w).toLowerCase().includes(q.toLowerCase())) return false;
return true;
});
list.sort((a, b) => TR(a.t) - TR(b.t) || a.n.localeCompare(b.n));
const slotStatus = (k) => { const v = curve[k] || 0; const [lo, hi] = CT[k]; return v < lo ? "lo" : v > hi ? "hi" : "ok"; };
const slotWord = (s) => s === "lo" ? "need more" : s === "hi" ? "trim" : "on target";
return (
<div className="msh">
<link href="https://fonts.googleapis.com/css2?family=Oswald:wght@500;600;700&family=Barlow:wght@400;500;600&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet" />
<style>{CSS}</style>
<header className="hd">
<div className="hd-stripe" />
<div className="hd-row">
<div className="hd-badge">MSH</div>
<div>
<div className="hd-title">Marvel Super Heroes</div>
<div className="hd-sub">Sealed Command \u00B7 Prerelease Deck-Build Dossier</div>
</div>
<div className="hd-stamp">Objective: Win</div>
</div>
</header>
<div className="stick">
<nav className="tabs">
{TABS.map(([k, lab]) => <button key={k} className={"tab" + (tab === k ? " on" : "")} onClick={() => setTab(k)}>{lab}</button>)}
</nav>
<button className="hud" onClick={() => setTab("pool")}>
{poolCards.length === 0
? <><span>No cards tagged yet \u2014 tap <b>+ Add to pool</b> on cards as you open them.</span><span className="go">tap \u2192 My Pool</span></>
: <>
<span>POOL <b>{poolCards.length}</b></span>
<span>BOMBS <b>{bombTot}</b></span>
<span>REMOVAL <b>{remTot}</b></span>
{rec.length >= 2 && <span className="deploy">\u25B8 DEPLOY {CNAME[rec[0]]} + {CNAME[rec[1]]}{arch ? " \u00B7 " + arch[3] : ""}</span>}
<span className="go">tap \u2192 My Pool</span>
</>}
</button>
</div>
<main className="wrap">
{tab === "play" && <>
<div className="call red"><b>Heads up before you start:</b> this is prerelease theorycraft \u2014 no real win-rate data exists yet (the set hits Arena around June 25). The grades and the archetype ranking will move once data lands. Treat this as a strong starting map, not gospel.</div>
<div className="eyebrow first">Color key</div>
<div className="panel">
<div className="legend">
{["W", "U", "B", "R", "G"].map((x) => <span key={x} className="lg"><span className={"pip " + x}>{x}</span>{CNAME[x]}</span>)}
<span className="lg"><span className="pip gold">{"\u2605"}</span>Multicolor</span>
<span className="lg"><span className="pip A">{"\u25C6"}</span>Artifact / colorless</span>
</div>
<div className="call" style={{ marginTop: 12, marginBottom: 0 }}><b>The one that trips people up:</b> the blue mana symbol is the letter <b>U</b> (not B \u2014 that's Black). So whenever you see "U/B" it means <b>Blue + Black</b>. Full glossary lives in the Key tab.</div>
</div>
<div className="eyebrow">Field orders</div>
<h2 className="h2">The 5 rules that win this format</h2>
<div className="panel">
{[
["Bombs and removal win.", "It's a bomb-dense set. Find your best bomb, build the deck that supports it, and play every good removal spell you own."],
["White, Black, and Red are the power colors.", "They hold the best removal and both perfect-rated bombs (Captain Marvel in White, Doctor Doom in Black). When unsure, base your deck in two of these \u2014 White + Black is the safest premium pair."],
["\u201CDeals 4\u201D or \u201Cdestroy toughness 4 or less\u201D is near-unconditional removal.", "That kills about 89% of creatures \u2014 rank those spells highest. Rank \u201Cdeals 2\u201D effects much lower."],
["Don't force synergy decks in Sealed.", "Especially Teamwork (only ~12 cards, mostly small bonuses) and Blue/Red Artifacts (needs more artifacts than you'll reliably open). Good cards beat cute synergy."],
["Curve discipline plus 17 lands.", "Power-up creatures flex between a cheap and an expensive slot. Splash only a single off-color bomb, using a dual land, Treasure, Dependable Quinjet, or Undercover Skrull \u2014 never a clean third color."],
].map(([h, p], i) => <div className="order" key={i}><div className="order-n">{i + 1}</div><div><h3>{h}</h3><p>{p}</p></div></div>)}
</div>
<div className="eyebrow">Color power</div>
<div className="grid g2">
{[["W", "White", "The aggressive color and best removal hub (45 creatures, 37 Heroes). Home of Captain Marvel."], ["B", "Black", "The most efficient removal plus the format's best bomb, Doctor Doom."], ["R", "Red", "The widest removal: burn, Thor, and the board wipe (Avengers Disassembled)."], ["U", "Blue", "Tempo and tricks but few hard answers \u2014 best as a support color."], ["G", "Green", "Ramp, fixing, and big bodies, but thin on removal. Your splash enabler lives here (Undercover Skrull)."], ["gold", "Multicolor / colorless", "Gold cards are two-color signposts; The Mind Stone and Mjolnir are bombs that slot into any deck."]].map(([code, name, desc]) => (
<div className="cpow" key={name} style={{ "--cc": ccVar(code) }}><h3><Pips c={code} />{name}</h3><p>{desc}</p></div>
))}
</div>
<div className="eyebrow">The removal rule</div>
<div className="call"><b>Rank removal by how unconditional it is.</b> Spells that deal 4 damage, or destroy a creature with toughness 4 or less, hit about 89% of the creatures in this set \u2014 treat those as premium and grab them first. Exile effects (like Murdock's Crusade) and "destroy" effects also beat indestructible. A spell that only "deals 2" is a real downgrade \u2014 rank it lower and don't lean on it.</div>
<div className="eyebrow">How to pick your two colors</div>
<div className="panel">
<p className="lead">Don't pick by favorite hero. For each color, count two numbers \u2014 how many bombs and threats you opened, and how much removal \u2014 then take the two colors with the highest combined total, leaning toward White, Black, or Red on ties. As you tag cards, the My Pool tab counts this for you and names the deck.</p>
<button className="btn" onClick={() => setTab("pool")}>Open My Pool tracker</button>
</div>
</>}
{tab === "cards" && <>
<div className="eyebrow first">Scouting report</div>
<h2 className="h2">Every flagged card, by color</h2>
<p className="lead">Now includes the <b>top commons by color</b> (ranked) so you can spot the role-players that pair with your deck. Tap <b>+ Add to pool</b> as you open the good ones and your colors get ranked live in My Pool. Tap <b>Commons</b> below to see only commons. Cards not listed? Bring them to me in chat and I'll slot them.</p>
<div className="filt">
<div className="frow"><span className="flab">Color</span>
{[["all", "All"], ["W", "White"], ["U", "Blue"], ["B", "Black"], ["R", "Red"], ["G", "Green"], ["multi", "Multicolor"], ["A", "Artifact"]].map(([k, l]) => <button key={k} className={"fbtn" + (fC === k ? " on" : "")} onClick={() => setFC(k)}>{l}</button>)}
</div>
<div className="frow"><span className="flab">Grade</span>
{[["all", "All"], ["S", "S"], ["A", "A"], ["B", "B"], ["C", "C"]].map(([k, l]) => <button key={k} className={"fbtn" + (fT === k ? " on" : "")} onClick={() => setFT(k)}>{l}</button>)}
<span className="flab" style={{ minWidth: "auto", marginLeft: 6 }}>Role</span>
{[["all", "All"], ["bomb", "Bombs"], ["rem", "Removal"], ["common", "Commons"], ["trap", "Traps"]].map(([k, l]) => <button key={k} className={"fbtn" + (fR === k ? " on" : "")} onClick={() => setFR(k)}>{l}</button>)}
</div>
<div className="frow">
<input className="search" placeholder="Search card names or text..." value={q} onChange={(e) => setQ(e.target.value)} />
<span className="count">{list.length} cards</span>
</div>
</div>
<div className="cards">
{list.map((c) => {
const inP = pool.includes(c.n);
return (
<div key={c.n} className={"card" + (inP ? " inpool" : "")} style={{ "--cc": ccVar(c.c) }}>
<div className="ctop"><Pips c={c.c} /><span className="cname">{c.n}</span><Bdg t={c.t} /></div>
<div className="cmeta">
<span className="tag">{RAR(c.r)}</span>
{isTrap(c) ? <span className="tag trap">Trap \u2014 avoid</span> : <span className="tag">{c.o}</span>}
</div>
<div className="cwhy">{c.w}</div>
<button className={"pbtn" + (inP ? " on" : "")} onClick={() => togglePool(c.n)}>{inP ? "\u2713 In your pool" : "+ Add to pool"}</button>
</div>
);
})}
</div>
</>}
{tab === "pool" && <>
<div className="eyebrow first">Live build</div>
<h2 className="h2">My pool</h2>
{poolCards.length === 0
? <div className="empty">Tag cards in the <b>Cards</b> tab as you open them. The moment you do, I'll count your bombs and removal per color and tell you which two colors to build.<br /><br /><button className="btn" onClick={() => setTab("cards")}>Go to Cards</button></div>
: <>
<div className="stat-grid">
<div className="stat"><div className="v">{poolCards.length}</div><div className="k">cards tagged</div></div>
<div className="stat"><div className="v" style={{ color: "var(--gold)" }}>{bombTot}</div><div className="k">bombs</div></div>
<div className="stat"><div className="v" style={{ color: "var(--r)" }}>{remTot}</div><div className="k">removal</div></div>
</div>
{rec.length >= 2
? <div className="deploybox">
<div className="dh">{"\u25B8 Deployment orders"}</div>
<div className="dt"><Pips c={rec[0]} /> {CNAME[rec[0]]} <span style={{ color: "var(--ink3)" }}>+</span> <Pips c={rec[1]} /> {CNAME[rec[1]]}</div>
<div className="ds">{arch ? <><b>{arch[3]}</b> \u2014 ranked #{arch[0]} of 10 for Sealed. {arch[4]}</> : <>Your strongest two-color base by bomb and removal count.</>}</div>
</div>
: <div className="call">Tag a few more cards \u2014 you need playables in a second color before I can lock in a pair.</div>}
<div className="eyebrow">Color counts (your two numbers)</div>
<table className="ptab">
<thead><tr><th>Color</th><th className="num">Bombs</th><th className="num">Removal</th><th className="num">Playables</th><th className="num">Score</th></tr></thead>
<tbody>
{COLS.split("").map((X) => {
const s = stat[X]; const isTop = rec.includes(X) && rec.length >= 2;
return <tr key={X} className={isTop ? "top" : ""}><td><Pips c={X} /> {CNAME[X]}</td><td className="num">{s.bombs}</td><td className="num">{s.rem}</td><td className="num">{s.play}</td><td className="num sc">{s.score.toFixed(1)}</td></tr>;
})}
</tbody>
</table>
<p className="ctgt" style={{ marginTop: 6 }}>Score weights bombs highest, then removal, then other playables \u2014 the two highlighted colors are your build. Bombs and removal win, so trust those columns.</p>
{rec.length >= 2 && <>
<div className="eyebrow">Your shortlist \u2014 build down from here</div>
<div className="call" style={{ marginTop: 0 }}>Your tagged cards in <b>{CNAME[rec[0]]} + {CNAME[rec[1]]}</b>, best grade first. <b>Play every bomb</b>, then your best <b>6\u20138 removal</b>, then fill with your best bodies toward <b>~15 creatures</b>. A full deck is <b>23 spells + 17 lands</b>.</div>
<p className="ctgt" style={{ margin: "2px 0 4px" }}>In your colors now: <b style={{ color: slSpellN >= 23 ? "var(--g)" : "var(--gold)" }}>{slSpellN} spells</b> ({slBombs.length} {slBombs.length === 1 ? "bomb" : "bombs"}, {slRem.length} removal, {slBodies.length} other){slSpellN >= 23 ? " \u2014 enough; cut your lowest-grade bodies down to 23." : slSpellN >= 18 ? " \u2014 almost there; round out with your best filler or a splash bomb." : " \u2014 keep tagging, or dip into lower-grade cards / a splash to reach 23."}</p>
<SlList label="Bombs \u2014 play them all" cards={slBombs} accent="gold" />
<SlList label="Removal & interaction \u2014 play your best 6\u20138" cards={slRem} accent="red" />
<SlList label="Bodies & value \u2014 fill toward ~15 creatures" cards={slBodies} />
<SlList label="Mana fixing / utility lands" note="don't count toward 23 spells" cards={slLandList} accent="dim" />
{slCut.length > 0 && <SlList label="Off-color \u2014 leave out (unless you splash)" cards={slCut} accent="dim" />}
{slTrap.length > 0 && <div className="call red" style={{ marginTop: 8 }}><b>Traps you tagged:</b> {slTrap.map((c) => c.n).join(", ")} \u2014 leave these in the box.</div>}
</>}
{flex.length > 0 && <><div className="eyebrow">Colorless bombs (play in any deck)</div><ul className="ul">{flex.map((c) => <li key={c.n}><b>{c.n}</b> \u2014 {c.w}</li>)}</ul></>}
{offBombs.length > 0 && <><div className="eyebrow">Splash watch</div><div className="call"><b>Off-color bombs you opened:</b> {offBombs.map((c) => c.n).join(", ")}. Splash <em>one</em> of these only if you have at least two fixers. {fixers.length > 0 ? <>Fixers in your pool: <b>{fixers.map((c) => c.n).join(", ")}</b>.</> : <>You have no fixers tagged yet \u2014 grab a dual land, Undercover Skrull, or Dependable Quinjet first.</>}</div></>}
<div className="eyebrow">Curve tracker</div>
<p className="ctgt" style={{ marginBottom: 10 }}>Count your chosen spells by cost and punch them in. Green dot = on target, gold = add more, red = trim. Goal: 23 nonland cards + 17 lands = 40.</p>
<div className="curve">
{[1, 2, 3, 4, 5, 6].map((k) => {
const s = slotStatus(k);
return <div className="crow" key={k}>
<span className="clab">{SLOTLAB[k]}</span>
<span className="step"><button className="sbtn" onClick={() => setC(k, -1)}>{"\u2212"}</button><span className="sval">{curve[k] || 0}</span><button className="sbtn" onClick={() => setC(k, 1)}>+</button></span>
<span className="ctgt"><span className={"dot " + s} />target {CT[k][0]}{CT[k][1] !== CT[k][0] ? "\u2013" + CT[k][1] : ""} \u00B7 {slotWord(s)}</span>
</div>;
})}
<div className="crow" style={{ borderTop: "1px solid var(--line)", paddingTop: 10, marginTop: 2 }}>
<span className="clab">Lands</span>
<span className="step"><button className="sbtn" onClick={() => setC("L", -1)}>{"\u2212"}</button><span className="sval">{curve.L || 0}</span><button className="sbtn" onClick={() => setC("L", 1)}>+</button></span>
<span className="ctgt"><span className={"dot " + (curve.L === 17 ? "ok" : curve.L < 17 ? "lo" : "hi")} />target 17</span>
</div>
</div>
<p className="ctgt" style={{ marginTop: 10 }}>Spells so far: <b style={{ color: totalSpells === 23 ? "var(--g)" : "var(--gold)" }}>{totalSpells} / 23</b> \u00B7 with lands: {totalSpells + (curve.L || 0)} / 40. Also aim for ~15\u201317 creatures and ~6\u20138 removal spells.</p>
<div style={{ marginTop: 18 }}><button className="btn ghost" onClick={clearPool}>Clear pool</button></div>
</>}
</>}
{tab === "arch" && <>
<div className="eyebrow first">The ten decks</div>
<h2 className="h2">Archetypes, ranked for Sealed</h2>
<p className="lead">Ranked by removal density, bomb density, and how forgiving the deck is when you can't assemble its synergy. Synergy-dependent decks fall; good-cards decks in strong colors rise. This ranking is the least-certain part of the guide \u2014 expect it to shift once data lands. Top three are expanded.</p>
{ARCH.map((a) => (
<div className="arow" key={a[0]}>
<div className={"arank" + (a[0] <= 3 ? " r" + a[0] : "")}>{a[0]}</div>
<div style={{ flex: 1 }}>
<div className="aname">{a[3]}</div>
<div className="apair">{a[2]}</div>
<div className="adesc">{a[4]}</div>
{a[5] && <div className="adetail"><div><b>Signposts</b> {a[5].s}</div><div><b>Glue</b> {a[5].g}</div><div><b>Best combo</b> {a[5].c}</div></div>}
</div>
</div>
))}
<div className="eyebrow">Two-card combos to watch</div>
<p className="lead">Synergy pairings highlighted in Draftsim's guide \u2014 grab both halves when you can. (I couldn't pull the specific combo from the video you linked \u2014 YouTube blocked the transcript from here \u2014 so these are the sourced written equivalents.)</p>
{COMBO.map(([a, b, why]) => (
<div className="combo" key={a + b}>
<div className="cpair"><span>{a}</span><span className="plus">+</span><span>{b}</span></div>
<p>{why}</p>
</div>
))}
</>}
{tab === "mech" && <>
<div className="eyebrow first">Rules reference</div>
<h2 className="h2">Mechanics, in plain English</h2>
<p className="lead">What each keyword does and how it should change the way you build.</p>
{MECH.map(([name, plain, imp]) => (
<div className="mech" key={name}><h3>{name}</h3><div className="plain">{plain}</div><div className="imp"><b>Build impact</b>{imp}</div></div>
))}
</>}
{tab === "check" && <>
<div className="eyebrow first">15-minute build</div>
<h2 className="h2">Your build checklist</h2>
<p className="lead">Tap each step as you finish it \u2014 your progress is saved.</p>
{STEPS.map(([h, p], i) => (
<div key={i} className={"stepitem" + (done.includes(i) ? " done" : "")} onClick={() => toggleStep(i)}>
<div className="chk">{"\u2713"}</div>
<div><h3><span className="sn">Step {i + 1}</span>{h}</h3><p>{p}</p></div>
</div>
))}
<div className="eyebrow">Mulligan and sequencing</div>
<ul className="ul">{MULL.map((m, i) => <li key={i}>{m}</li>)}</ul>
<div className="eyebrow">Sideboarding between games</div>
<ul className="ul">{SIDE.map(([m, p], i) => <li key={i}><b>{m}:</b> {p}</li>)}</ul>
</>}
{tab === "temp" && <>
<div className="eyebrow first">Starting points</div>
<h2 className="h2">Three sample 23-spell decklists</h2>
<p className="lead">Slots are roles, not exact lists \u2014 fill each with the best card you opened in that role. All counts assume 17 lands.</p>
{TMPL.map((t) => (
<div className="tmpl" key={t.name} style={{ "--cc": t.cc }}>
<div className="tmpl-h"><h3>{t.name}</h3><div className="play"><b style={{ color: "var(--ink)" }}>Play to win:</b> {t.play}</div></div>
{t.rows.map((r, i) => <div className="slot" key={i}><span className="role">{r[0]}</span><span className="cnt">{r[1]}</span><span className="ex">{r[2]}</span></div>)}
<div className="land">+ 17 lands = 40 cards</div>
</div>
))}
</>}
{tab === "key" && <>
<div className="eyebrow first">Decoder</div>
<h2 className="h2">Key & glossary</h2>
<p className="lead">Every abbreviation and term, spelled out. When in doubt, it's here.</p>
<dl className="kg">
{KEY.map(([title, items]) => <div key={title}><dt>{title}</dt>{items.map(([k, v]) => <dd key={k}><span className="k">{k}</span><span>{v}</span></dd>)}</div>)}
<div><dt>The removal rule</dt><dd><span className="k">89% rule</span><span>"Deals 4 damage" or "destroy a creature with toughness 4 or less" kills about 89% of creatures \u2014 rank those highest. "Deals 2" is much weaker, so rank it lower.</span></dd></div>
</dl>
</>}
</main>
<footer className="ft">
Built from the prerelease build guide \u2014 expert theorycraft dated <b>June 19, 2026</b>. No win-rate data exists yet; the set hits Arena around June 25, and the grades and archetype ranking will shift once 17Lands data lands.<br />
Card grades and combos synthesized from WotC's Prerelease Guide, TCGplayer (LSV, Reid Duke), Draftsim (Bryan Hohns \u2014 top-common rankings and combos), and Cardsrealm. Your tagged pool, curve, and checklist are saved in this browser.
</footer>
</div>
);
}
```
[REQUESTED CHANGES]
(no specific request — apply your best judgment)
--- HOW TO RESPOND (READ FIRST) ---
Before writing any code, follow this exact process:
1. **ANALYZE** the widget source code provided above and identify:
a. Which Vibes SDK features it already uses (vibes.save, vibes.load, vibes.shared.join, etc.)
b. Which SDK features would genuinely benefit THIS specific widget — tailored to what it does, not a dump of everything available.
2. **PRESENT A NUMBERED LIST** covering:
- SDK features currently active in this widget
- New SDK features that would concretely improve this widget (be specific: why this widget, what it enables)
3. **WAIT** — do not write any code yet. Reply with your analysis and numbered list, then stop and ask the user which numbered items they want.
4. **IMPLEMENT ONLY** the items the user confirms, plus any explicit change they requested. Do not add unrequested features.
**IMPORTANT — Shared state room names:**
If you add vibes.shared.join(), do NOT use a hardcoded string literal as the room name (e.g. vibes.shared.join("lobby")) unless the user explicitly wants ALL viewers to share one single global state. A hardcoded room name means every person who visits this widget reads and writes the same shared state — it is a global room. For per-user or per-session isolation, derive the room name from a variable (e.g. a user ID, session token, or random value). When in doubt, use vibes.save/vibes.load for per-user persistence instead.
--- VIBES SDK CONTEXT ---
## Vibes SDK Reference
You are building an HTML widget for It Just Vibes (itjustvibes.com). The Vibes SDK is auto-injected — do NOT add a script tag. Just use `window.vibes` (or just `vibes`).
### Setup
Wrap your startup code in `vibes.onReady`:
```js
vibes.onReady(async () => {
const saved = await vibes.load("myKey");
// your widget logic here
});
```
### State (Per-User Persistence)
Every user gets their own isolated state per widget. All methods return Promises.
| Method | Description |
|--------|-------------|
| `await vibes.save(key, value)` | Save JSON-serializable data |
| `await vibes.load(key)` | Load saved data (returns `null` if not found) |
| `await vibes.delete(key)` | Delete a saved key |
| `await vibes.listKeys()` | Get array of all saved key names |
**Key rules:**
- Keys are strings, max 64 characters, alphanumeric + dashes/underscores
- Values must be JSON-serializable (objects, arrays, strings, numbers, booleans)
- Max 100KB per value, 500KB per widget per user, 5MB per user total
- Max 100 keys per widget per user
### Fetch Proxy
Use direct `fetch()` for APIs with permissive CORS headers (`Access-Control-Allow-Origin: *`). Use `vibes.fetch` for APIs without CORS headers (the proxy handles cross-origin requests):
```js
const resp = await vibes.fetch("https://api.example.com/data", {
method: "GET", // GET, POST, PUT, DELETE
headers: {}, // optional headers
body: null, // optional body (string)
timeout: null // optional timeout in ms
});
const data = await resp.json(); // or resp.text()
console.log(resp.status, resp.ok);
```
### Multiplayer (Shared State)
Real-time shared state across all users viewing the same widget.
```js
// Join a room (call once at startup)
await vibes.shared.join("lobby", { persistent: true });
// Set shared state (broadcasts to all users)
await vibes.shared.set("score", { player1: 10, player2: 7 });
// Read shared state (synchronous, returns last known value)
const score = vibes.shared.get("score");
// Listen for changes to a specific key
vibes.shared.onChange("score", (newValue) => {
console.log("Score updated:", newValue);
});
// Listen for any shared state change
vibes.shared.onAny((key, value) => {
console.log(key, "changed to", value);
});
// Get number of connected users
const count = await vibes.shared.getUserCount();
// Leave room
vibes.shared.leave();
// Clear all shared state for this room
await vibes.shared.clear();
```
**Shared state options:**
- `{ persistent: true }` — state survives page reloads (stored server-side)
- Default room name is "__default__" if omitted
### Agent-Accessible State (vibes.ai.*)
State written with the standard `vibes.save` / `vibes.load` methods is private to each user and is **NOT readable by AI agents**. To share state with an AI agent (via the MCP connector), use the `vibes.ai` sub-namespace:
| Method | Description |
|--------|-------------|
| `await vibes.ai.setState(key, value)` | Write agent-readable state. Key is stored internally as `ai/<key>`. |
| `await vibes.ai.getState(key)` | Read agent-readable state. Returns `null` if key absent. |
| `await vibes.ai.listKeys()` | List all agent-readable keys (without the `ai/` prefix). |
**Important rules:**
- Regular `vibes.save()` / `vibes.setState()` is **NOT agent-accessible** — use `vibes.ai.*` for state you want agents to read.
- The widget **owner** must enable agent access in **Manage → Agent tab** before any agent can read or write `vibes.ai.*` state.
- Keys are auto-prefixed to `ai/` internally; you supply just the short key (e.g. `'context'`).
```js
vibes.onReady(async () => {
// Write state an AI agent can later read
await vibes.ai.setState('context', { currentLevel: 3, score: 1500 });
// Read it back (same auto-prefix applies)
const ctx = await vibes.ai.getState('context');
// List all agent-accessible keys for this widget
const keys = await vibes.ai.listKeys(); // e.g. ['context']
});
```
### Rules
1. **Do NOT use localStorage, sessionStorage, or window.storage** — they are blocked or undefined in the sandbox. Use `vibes.save`/`vibes.load` instead.
2. **Do NOT add a script tag to import the SDK** — it is auto-injected.
3. **Wrap startup code in `vibes.onReady()`** — the SDK may not be ready immediately.
4. **Await all SDK calls** — every method (except `vibes.shared.get`) returns a Promise.
5. **Do NOT import external JS libraries via script tags** — they will be blocked. Include library code inline or use a CDN link in a `<link>` tag for CSS only.
6. **Keep total code under 80KB** — that is the default widget size limit (your account limit may be higher).
### Rate Limits
| Operation | Limit |
|-----------|-------|
| Writes (save + delete combined) | 30/min |
| Reads (load) | 60/min |
| List keys | 30/min |
| Fetch proxy | Rate limited per widget |
### Error Handling
All SDK methods can reject. Wrap in try/catch:
```js
try {
await vibes.save("key", value);
} catch (err) {
console.error("Save failed:", err.message);
}
```
Fetch proxy errors include `err.code`: `"RATE_LIMITED"`, `"BLOCKED"`, `"FETCH_ERROR"`.
### Data Export
Export rows of data as CSV or Excel directly from your widget.
```js
// Register dataset for the platform's "Export data" button
// AND optionally trigger an immediate download
vibes.exportData(rows, { filename: 'results.csv' })
// rows: Array of arrays (each inner array is one row; first row = headers)
// options.filename: sets the download filename and format (csv or xlsx)
// options.directDownload: false to only register without downloading (default: true)
```
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `filename` | string | `'data.csv'` | Download filename; extension determines format (`.csv` or `.xlsx`) |
| `directDownload` | boolean | `true` | Trigger immediate browser download in addition to registering the dataset |
**Notes:**
- First call registers the dataset so the widget chrome shows an "Export data" button
- Use `.csv` extension for CSV, `.xlsx` for Excel
- CSV injection safety is automatic (formula-starting cells prefixed with `'`)
- Data stays in the browser — no server round-trip
--- FORK & RESUBMIT INSTRUCTION ---
Return the complete, self-contained JSX file with all changes applied.
It should be ready to paste into itjustvibes.com/submit to create a new fork.
Include this comment at the top of the output:
/* Forked from: https://itjustvibes.com/Owner/marvel-super-heroes-sealed-win-dossier */