Duelingbook Deck Cost Tracker (Userscript)

Displays custom point costs on cards in Duelingbook's deck editor and search results.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Duelingbook Deck Cost Tracker (Userscript)
// @namespace    zayn-db-costs
// @version      1.5
// @description  Displays custom point costs on cards in Duelingbook's deck editor and search results.
// @match        https://www.duelingbook.com/*
// @run-at       document-idle
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  const MAX_COST = 100;
  const DEFAULT_COST = 0;

  const cardCosts = {
    "abyss dweller": 100,
    "adamancipator risen - dragite": 20,
    "agido the ancient sentinel": 50,
    "albion the sanctifire dragon": 33,
    "allure of darkness": 5,
    "amorphactor pain, the imagination dracoverlord": 100,
    "ancient gear advance": 33,
    "ancient gear statue": 33,
    "and the band played on": 100,
    "angel o7": 100,
    "anti-spell fragrance": 100,
    "appointer of the red lotus": 50,
    "arahime the manifested mikanko": 33,
    "arcana force xxi - the world": 100,
    "archlord kristya": 100,
    "archnemeses eschatos": 100,
    "archnemeses protos": 100,
    "artifact scythe": 100,
    "asceticism of the six samurai": 10,
    "ash blossom & joyous spring": 15,
    "assault synchron": 5,
    "astral kuriboh": 3,
    "atlantean dragoons": 40,
    "azamina ilia silvia": 20,
    "azamina mu rcielago": 33,
    "bahamut shark": 81,
    "baronne de fleur": 85,
    "barrier of the voiceless voice": 33,
    "barrier statue of the abyss": 60,
    "barrier statue of the drought": 60,
    "barrier statue of the heavens": 60,
    "barrier statue of the inferno": 60,
    "barrier statue of the stormwinds": 60,
    "barrier statue of the torrent": 60,
    "beatrice, lady of the eternal": 100,
    "big welcome labrynth": 33,
    "blackwing - boreastorm the wicked wind": 20,
    "blackwing - chinook the snow blast": 5,
    "blackwing - zephyros the elite": 15,
    "blaster, dragon ruler of infernos": 7,
    "blaze fenix, the burning bombardment bird": 70,
    "blazing cartesia, the virtuous": 3,
    "block dragon": 40,
    "bonfire": 33,
    "book of eclipse": 5,
    "book of moon": 7,
    "brain research lab": 100,
    "branded expulsion": 33,
    "branded fusion": 33,
    "branded lost": 66,
    "brilliant fusion": 33,
    "butterfly dagger - elma": 1,
    "bystial baldrake": 30,
    "bystial dis pater": 10,
    "bystial druiswurm": 30,
    "bystial magnamhut": 33,
    "bystial saronir": 20,
    "called by the grave": 20,
    "card destruction": 40,
    "card of demise": 40,
    "card of safe return": 40,
    "catapult turtle": 100,
    "centur-ion auxila": 33,
    "centur-ion primera": 5,
    "centur-ion trudea": 3,
    "chain strike": 50,
    "change of heart": 10,
    "chaofeng, phantom of the yang zing": 13,
    "chaos angel": 20,
    "chaos dragon levianeer": 10,
    "chaos ruler, the chaotic magical dragon": 50,
    "chaos space": 40,
    "charge of the light brigade": 33,
    "cold wave": 100,
    "confiscation": 100,
    'contact "c"': 100,
    "cornfield coatl": 33,
    "cosmic blazar dragon": 1,
    "creature swap": 1,
    "crimson dragon": 100,
    "crossout designator": 10,
    "crystron inclusion": 33,
    "crystron smiger": 5,
    "crystron sulfador": 3,
    "crystron thystvern": 5,
    "cyber angel benten": 40,
    "cyber dragon infinity": 20,
    "cyber jar": 33,
    "cyber-stein": 27,
    "d/d/d duo-dawn king kali yuga": 77,
    "d/d/d wave high king caesar": 20,
    "daigusto emeral": 1,
    "danger! bigfoot!": 3,
    "danger! chupacabra!": 3,
    "danger! dogman!": 3,
    "danger! mothman!": 3,
    "danger! nessie!": 7,
    "danger! ogopogo!": 3,
    "danger! thunderbird!": 3,
    "danger!? jackalope?": 7,
    "danger!? tsuchinoko?": 7,
    "dark end evaporation dragon": 5,
    "dark hole": 3,
    "dark world archives": 5,
    "deception of the sinful spoils": 33,
    "deck lockdown": 100,
    "deep sea aria": 33,
    "delinquent duo": 100,
    "denglong, first of the yang zing": 33,
    "denko sekka": 20,
    "destiny hero - destroyer phoenix enforcer": 20,
    "destiny hero - plasma": 20,
    "destructive daruma karma cannon": 5,
    "diabell, queen of the white forest": 25,
    "diabellstar the black witch": 20,
    "different dimension ground": 10,
    "dimension fusion": 45,
    "dimension shifter": 5,
    "dimensional barrier": 100,
    "dinomorphia intact": 1,
    "dinomorphia rexterm": 91,
    "dinowrestler pankratops": 10,
    "divine arsenal aa-zeus - sky thunder": 20,
    "diviner of the herald": 33,
    "djinn releaser of rituals": 100,
    "dogmatika ecclesia, the virtuous": 3,
    "domain of the true monarchs": 50,
    "dominus impulse": 30,
    "dominus purge": 10,
    "dracotail arthalion": 10,
    "dracotail faimena": 20,
    "dracotail mululu": 5,
    "dragon master magia": 100,
    "dragonic diagram": 33,
    "dragonmaid sheou": 20,
    "dragonmaid tidying": 10,
    "dragon's bind": 100,
    "dragon's light and darkness": 7,
    "droll & lock bird": 7,
    "drytron alpha thuban": 33,
    "drytron mu beta fafnir": 33,
    "duality": 10,
    "eclipse wyvern": 33,
    "effect veiler": 7,
    "el shaddoll apkallone": 10,
    "el shaddoll winda": 60,
    "elder entity norden": 91,
    "elder entity n'tss": 7,
    "elemental hero stratos": 3,
    "elzette, azamina of the white forest": 22,
    "emergency teleport": 40,
    "emergency!": 33,
    "eva": 1,
    "evenly matched": 10,
    "ext ryzeal": 25,
    "f.a. dawn dragster": 20,
    "fairy tail - snow": 85,
    "fiber jar": 30,
    "final countdown": 100,
    "fire formation - tenki": 40,
    "fire king courtier ulcanix": 20,
    "fire king high avatar kirin": 10,
    "fishborg blaster": 33,
    "floowandereeze & robina": 33,
    "floowandereeze and the advent of adventure": 33,
    "floowandereeze and the magnificent map": 33,
    "foolish burial": 33,
    "forbidden chalice": 5,
    "forbidden droplet": 10,
    "forbidden lance": 3,
    "fossil dig": 40,
    "fossil dyna pachycephalo": 100,
    "frightfur patchwork": 33,
    "fusion destiny": 33,
    "gallant granite": 33,
    "gateway of the six": 100,
    "gem-knight master diamond": 66,
    "ghost belle & haunted mansion": 5,
    "ghost meets girl - a masterful mayakashi shiranui saga": 100,
    "ghost mourner & moonlit chill": 7,
    "ghost ogre & snow rabbit": 5,
    "ghost sister & spooky dogwood": 3,
    "giant trunade": 40,
    "gigantic spright": 20,
    "gimmick puppet nightmare": 70,
    "give and take": 91,
    "gladiator beast gyzarus": 20,
    "gladiator beast tamer editor": 20,
    "gladiator proving ground": 33,
    "gladiator rejection": 20,
    "glow-up bulb": 21,
    "goblin biker grand entrance": 33,
    "gold sarcophagus": 10,
    "gozen match": 100,
    "graceful charity": 40,
    "grapha, dragon lord of dark world": 5,
    "grapha, dragon overlord of dark world": 5,
    "gruesome grave squirmer": 1,
    "guardian chimera": 33,
    "guiding quem, the virtuous": 3,
    "harpie's feather duster": 33,
    "harpie's feather storm": 100,
    "heart of the blue-eyes": 5,
    "heat wave": 100,
    "heavy storm": 25,
    "herald of the arc light": 50,
    "hot red dragon archfiend king calamity": 1,
    "hyper rank-up-magic utopiforce": 1,
    "ice ryzeal": 20,
    "ido the supreme magical force": 100,
    "imperial order": 100,
    "imsety, glory of horus": 33,
    "incoming machine!": 33,
    "incredible ecclesia, the virtuous": 3,
    "infernal flame banshee": 33,
    "infernity launcher": 88,
    "infinite impermanence": 15,
    "inspector boarder": 20,
    "instant fusion": 100,
    "interrupted kaiju slumber": 33,
    "into the void": 1,
    "invoked caliga": 90,
    "jet synchron": 1,
    "jowgen the spiritualist": 100,
    "junk speeder": 100,
    'k9-17 "ripper"': 20,
    "k9-17 izuna": 20,
    "k9-øø lupis": 5,
    "kaiser colosseum": 100,
    "kashtira arise-heart": 97,
    "kashtira fenrir": 30,
    "kashtira unicorn": 30,
    "kelbek the ancient vanguard": 50,
    "keldo the sacred protector": 1,
    "king of the feral imps": 33,
    "king's sarcophagus": 33,
    "knight armed dragon, the armored knight dragon": 3,
    "knightmare corruptor iblee": 100,
    "koa'ki meiru drago": 75,
    "koa'ki meiru guardian": 3,
    "koa'ki meiru overload": 3,
    "koa'ki meiru sandman": 3,
    "koa'ki meiru wall": 3,
    "lady labrynth of the silver castle": 33,
    "lady's dragonmaid": 20,
    "last turn": 75,
    "last will": 100,
    "lavalval chain": 80,
    "legendary fire king ponix": 10,
    "legendary lord six samurai - shi en": 10,
    "legendary six samurai - shi en": 10,
    "level eater": 100,
    "life equalizer": 100,
    "light and darkness dragonlord": 20,
    "light barrier": 1,
    "light end sublimation dragon": 5,
    "lightning storm": 40,
    "lonefire blossom": 33,
    "lose 1 turn": 100,
    "lubellion the searing dragon": 33,
    "lyrilusc - independent nightingale": 1,
    "magical explosion": 75,
    "magical mid-breaker field": 60,
    "magical scientist": 95,
    "magician of black chaos max": 100,
    "majesty's fiend": 100,
    "mansion of the dreadful dolls": 100,
    "masked hero dark law": 70,
    "mass driver": 100,
    "master peace, the true dracoslaying king": 33,
    'maxx "c"': 50,
    "meizen the battle ninja": 20,
    "mementomictlan tecuhtlica - creation king": 33,
    "mementotlan bone party": 33,
    "mementotlan twin dragon": 33,
    "metamorphosis": 10,
    "mikanko water arabesque": 10,
    "millennium ankh": 3,
    "mind drain": 100,
    "mind master": 1,
    "mirage of nightmare": 10,
    "mirrorjade the iceblade dragon": 33,
    "miscellaneousaurus": 75,
    "mistake": 100,
    "mitsurugi prayers": 60,
    "mitsurugi ritual": 60,
    "monster gate": 50,
    "monster reborn": 20,
    "morphing jar": 33,
    "morphtronic telefon": 55,
    "moulinglacia the elemental lord": 100,
    "mudora the sword oracle": 1,
    "mulcharmy fuwalos": 7,
    "mulcharmy meowls": 5,
    "mulcharmy purulia": 10,
    "m-x-saber invoker": 33,
    "mystic mine": 100,
    "nadir servant": 33,
    "naturia barkion": 10,
    "naturia beast": 50,
    "naturia exterio": 100,
    "necrovalley": 40,
    "neptabyss, the atlantean prince": 33,
    "nibiru, the primal being": 10,
    "nightmare apprentice": 33,
    "nightmare throne": 50,
    "number 1: infection buzzking": 85,
    "number 1: numeron gate ekam": 10,
    "number 100: numeron dragon": 1,
    "number 16: shock master": 100,
    "number 2: numeron gate dve": 10,
    "number 3: numeron gate trini": 10,
    "number 38: hope harbinger dragon titanic galaxy": 10,
    "number 4: numeron gate catvari": 10,
    "number 40: gimmick puppet of strings": 50,
    "number 41: bagooska the terribly tired tapir": 100,
    "number 43: manipulator of souls": 100,
    "number 59: crooked cook": 100,
    "number 75: bamboozling gossip shadow": 70,
    "number 86: heroic champion - rhongomyniad": 31,
    "number 89: diablosis the mind hacker": 85,
    "number 90: galaxy-eyes photon lord": 10,
    "number 95: galaxy-eyes dark matter dragon": 50,
    "number 97: draglubion": 100,
    "number c1: numeron chaos gate sunya": 10,
    "number c40: gimmick puppet of dark strings": 50,
    "number s0: utopic zexal": 100,
    "numeron calling": 30,
    "numeron network": 33,
    "obedience schooled": 40,
    "one day of peace": 11,
    "one for one": 91,
    "onomatopaira": 33,
    "original sinful spoils - snake-eye": 100,
    "outer entity azathot": 100,
    "painful choice": 95,
    "phantom knights' rank-up-magic force": 1,
    "phantom of yubel": 50,
    "pilgrim reaper": 50,
    "pot of desires": 20,
    "pot of greed": 30,
    "pot of prosperity": 40,
    "powersink stone": 100,
    "premature burial": 27,
    "preparation of rites": 5,
    "pre-preparation of rites": 10,
    "pressured planet wraitsoth": 33,
    "primeval planet perlereino": 50,
    "primite lordly lode": 33,
    "psychic end punisher": 20,
    "psy-framegear delta": 7,
    "psy-framegear epsilon": 7,
    "psy-framegear gamma": 15,
    "psy-framelord omega": 100,
    "purrely": 15,
    "purrely sleepy memory": 15,
    "purrelyly": 10,
    "quick launch": 33,
    "raidraptor - vanishing lanius": 5,
    "raigeki": 7,
    "rank-up-magic - the seventh one": 1,
    "rank-up-magic admiration of the thousands": 1,
    "rank-up-magic argent chaos force": 5,
    "rank-up-magic astral force": 1,
    "rank-up-magic barian's force": 1,
    "rank-up-magic cipher ascension": 1,
    "rank-up-magic doom double force": 1,
    "rank-up-magic limited barian's force": 1,
    "rank-up-magic magical force": 1,
    "rank-up-magic numeron force": 1,
    "rank-up-magic quick chaos": 1,
    "rank-up-magic raid force": 1,
    "rank-up-magic raptor's force": 1,
    "rank-up-magic revolution force": 1,
    "rank-up-magic skip force": 5,
    "rank-up-magic soul shave force": 5,
    "rank-up-magic zexal force": 1,
    "ra's disciple": 1,
    "reasoning": 50,
    "red reboot": 50,
    "red-eyes dark dragoon": 100,
    "redox, dragon ruler of boulders": 7,
    "regenesis": 33,
    "reinforcement of the army": 40,
    "rescue-ace air lifter": 10,
    "rescue-ace preventer": 10,
    "return from the different dimension": 50,
    "return of the dragon lords": 10,
    "rise rank-up-magic raidraptor's force": 1,
    "rite of aramesir": 5,
    "ritual beast tamer elder": 10,
    "rivalry of warlords": 100,
    "ronintoadin": 60,
    "royal decree": 10,
    "royal magical library": 100,
    "royal oppression": 100,
    "ryzeal detonator": 20,
    "ryzeal duo drive": 20,
    "sangen kaimen": 50,
    "sangen summoning": 100,
    "sauravis, the ancient and ascended": 5,
    "schwarzschild infinity dragon": 33,
    "secret village of the spellcasters": 100,
    "self-destruct button": 100,
    "sengenjin wakes from a millennium": 33,
    "set rotation": 33,
    "shaddoll schism": 10,
    "shien's dojo": 10,
    "shien's smoke signal": 33,
    "shooting riser dragon": 33,
    "sillva, warlord of dark world": 100,
    "sixth sense": 65,
    "skill drain": 100,
    "smoke grenade of the thief": 87,
    "snake-eye ash": 5,
    "snake-eyes poplar": 5,
    "snatch steal": 7,
    "snoww, unlight of dark world": 33,
    "solemn judgment": 7,
    "solemn strike": 5,
    "solemn warning": 5,
    "songs of the dominators": 10,
    "soul charge": 50,
    "soul drain": 100,
    "speedroid terrortop": 3,
    "spell canceller": 20,
    "spiritual beast tamer lara": 10,
    "spright starter": 20,
    "stand up centur-ion!": 5,
    "stardust sifr divine dragon": 1,
    "starliege seyfert": 33,
    "stray purrely street": 5,
    "substitoad": 60,
    "subterror guru": 5,
    "summon limit": 100,
    "super polymerization": 10,
    "super starslayer ty-phon - sky crisis": 10,
    "supreme king dragon starving venom": 1,
    "swap frog": 33,
    "sword ryzeal": 20,
    "swordsoul emergence": 33,
    "swordsoul grandmaster - chixiao": 33,
    "swordsoul of mo ye": 3,
    "swordsoul strategist longyuan": 5,
    "t.g. hyper librarian": 33,
    "tearlaments havnis": 50,
    "tearlaments kitkallos": 50,
    "tearlaments merrli": 50,
    "tearlaments reinoheart": 50,
    "tearlaments scheiren": 50,
    "telekinetic charging cell": 100,
    "tellarknight ptolemaeus": 100,
    "tempest, dragon ruler of storms": 7,
    "tenpai dragon chundra": 50,
    "tenpai dragon genroku": 25,
    "tenyi spirit - ashuna": 33,
    "terraforming": 33,
    "that grass looks greener": 50,
    "the black goat laughs": 10,
    "the bystial lubellion": 30,
    "the forceful sentry": 100,
    "the gates of dark world": 5,
    "the hidden city": 33,
    "the last warrior from another planet": 100,
    "the melody of awakening dragon": 33,
    "the monarchs erupt": 50,
    "the phantom knights' rank-up-magic launch": 1,
    "the tyrant neptune": 100,
    "the unstoppable exodia incarnate": 20,
    "the zombie vampire": 50,
    "there can be only one": 100,
    "thunder dragon colossus": 67,
    "thunder king rai-oh": 20,
    "tidal, dragon ruler of waterfalls": 7,
    "toadally awesome": 20,
    "tour guide from the underworld": 3,
    "trap dustshoot": 94,
    "traptrix rafflesia": 10,
    "triple tactics talent": 93,
    "triple tactics thrust": 13,
    "trishula, dragon of the ice barrier": 3,
    "true king of all calamities": 100,
    "tyrant's tirade": 100,
    "ultimaya tzolkin": 100,
    "union hangar": 33,
    "vanity's emptiness": 100,
    "vanity's fiend": 100,
    "vanity's ruler": 100,
    "varudras, the final bringer of the end times": 20,
    "virtual world kyubi - shenshen": 20,
    "virtual world mai-hime - lulu": 3,
    "wandering gryphon rider": 20,
    "wanted: seeker of sinful spoils": 33,
    "water enchantress of the temple": 5,
    "welcome labrynth": 33,
    "wind-up carrier zenmaity": 33,
    "wind-up hunter": 75,
    "wishes for eyes of blue": 33,
    "witch of the white forest": 33,
    "yaguramaru the armor ninja": 20,
    "zaborg the mega monarch": 80,
    "zoodiac barrage": 33,
    "zoodiac broadbull": 66,
    "zoodiac drident": 20,
    "zoodiac ratpier": 50
  };

  function ensureTotalDisplay() {
    let totalDisplay = document.getElementById('deck-cost-display');
    if (!totalDisplay) {
      totalDisplay = document.createElement('div');
      totalDisplay.id = 'deck-cost-display';
      totalDisplay.style.position = 'fixed';
      totalDisplay.style.top = '40px';
      totalDisplay.style.right = '10px';
      totalDisplay.style.zIndex = '9999';
      totalDisplay.style.fontSize = '18px';
      totalDisplay.style.fontWeight = 'bold';
      totalDisplay.style.padding = '6px 12px';
      totalDisplay.style.borderRadius = '6px';
      totalDisplay.style.background = 'rgba(0,0,0,0.7)';
      totalDisplay.style.color = 'white';
      document.body.appendChild(totalDisplay);
    }
    return totalDisplay;
  }

  function ensureToggleButton() {
    let btn = document.getElementById('deck-cost-toggle');
    if (!btn) {
      btn = document.createElement('button');
      btn.id = 'deck-cost-toggle';
      btn.textContent = 'Hide Costs';
      btn.style.position = 'fixed';
      btn.style.top = '10px';
      btn.style.right = '10px';
      btn.style.zIndex = '10000';
      btn.style.padding = '4px 10px';
      btn.style.borderRadius = '6px';
      btn.style.background = 'black';
      btn.style.color = 'white';
      btn.style.fontWeight = 'bold';
      btn.style.cursor = 'pointer';
      btn.addEventListener('click', () => {
        costsEnabled = !costsEnabled;
        btn.textContent = costsEnabled ? 'Hide Costs' : 'Show Costs';
        updateDeckCosts();
      });
      document.body.appendChild(btn);
    }
    return btn;
  }

  let costsEnabled = true;

  function getOrCreateLabel(cardEl, cardId) {
    let label = cardEl.querySelector('.cost-label');

    const pos = getComputedStyle(cardEl).position;
    if (pos === 'static') {
      cardEl.style.position = 'relative';
    }

    let bottom = '50px';
    let background = 'rgba(0,0,0,0)';
    let color = 'rgba(0.2,0.2,0.2,0)';

    if (cardId === 'search_card17' || cardId === 'search_card18' || cardId === 'search_card19') {
      bottom = '350px';
      background = 'rgba(0,0,0,0.3)';
      color = 'yellow';
    }

    if (!label) {
      label = document.createElement('div');
      label.className = 'cost-label';
      label.style.position = 'absolute';
      label.style.bottom = bottom;
      label.style.left = '100px';
      label.style.background = background;
      label.style.color = color;
      label.style.fontSize = '200px';
      label.style.padding = '2px 4px';
      label.style.borderRadius = '4px';
      label.style.textShadow = `
        -2px -2px 0 black,
         2px -2px 0 black,
        -2px  2px 0 black,
         2px  2px 0 black,
         0px  0px 4px black
      `;
      label.style.fontWeight = '9000';
      cardEl.appendChild(label);
    }
    return label;
  }

  function updateDeckCosts() {
    ensureToggleButton();

    const selectors = ['.deck_card', '.extra_card', '.side_card', '.search_card'];
    let total = 0;

    for (const selector of selectors) {
      const cards = document.querySelectorAll(selector);
      for (const cardEl of cards) {
        if (!cardEl || cardEl.style.display === 'none') continue;

        const rawName = cardEl.querySelector('.name_txt')?.textContent?.trim() ?? '';
        const cost = cardCosts[rawName.toLowerCase()] ?? DEFAULT_COST;

        if (selector !== '.search_card') {
          total += cost;
        }

        const label = getOrCreateLabel(cardEl, cardEl.id);
        label.textContent = (costsEnabled && cost > 0) ? String(cost) : '';

        const scale = cardEl.querySelector('.scale_left_txt');
        if (scale && scale.style && scale.style.display !== 'none') {
          label.textContent = costsEnabled ? 'X' : '';
        }

        const image = cardEl.querySelector('.card_color');
        if (image && image.src === 'https://images.duelingbook.com/card/link_front2.webp') {
          label.textContent = costsEnabled ? 'X' : '';
        }
      }
    }

    const display = ensureTotalDisplay();
    display.style.display = costsEnabled ? 'block' : 'none';
    display.textContent = `Deck Cost: ${total} / ${MAX_COST}`;
    display.style.color = total > MAX_COST ? 'red' : 'lightgreen';
  }

  let updateScheduled = false;
  const observer = new MutationObserver(() => {
    if (!updateScheduled) {
      updateScheduled = true;
      requestAnimationFrame(() => {
        updateDeckCosts();
        updateScheduled = false;
      });
    }
  });

  function start() {
    if (!document.body) {
      requestAnimationFrame(start);
      return;
    }
    observer.observe(document.body, { childList: true, subtree: true });
    updateDeckCosts();
  }

  start();
})();