Torn Arson Helper

Contextual tooltips for Arson crime materials, job requirements, and unique targets

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Torn Arson Helper
// @namespace    https://github.com/pedroximeneztorn
// @version      1.1
// @description  Contextual tooltips for Arson crime materials, job requirements, and unique targets
// @author       PedroXimenez
// @match        https://*.torn.com/page.php?sid=crimes*
// @license      MIT
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // ── Data from cite.json ──────────────────────────────────────────────

    const ACCELERANTS = {
        "Gasoline": {
                "type": "Liquid",
                "intensity": "5%",
                "intensity_abs": 1.5,
                "momentum": "HIGH",
                "momentum_abs": 6,
                "spread": "37.5%",
                "ignition_risk": 1,
                "stoking_risk": 7,
                "suspicion": 9,
                "advice": "Use up to 1+Number of areas (max 6). Cheap but risky when stoking."
        },
        "Diesel": {
                "type": "Liquid",
                "intensity": "5.25%",
                "intensity_abs": 2,
                "momentum": "HIGH",
                "momentum_abs": 5,
                "spread": "16%",
                "ignition_risk": 0,
                "stoking_risk": 1,
                "suspicion": 7,
                "advice": "Lowers crit-rate on ignition, increases visibility. Best combined with solids."
        },
        "Kerosene": {
                "type": "Liquid",
                "intensity": "5.25%",
                "intensity_abs": 2,
                "momentum": "BEST",
                "momentum_abs": 10,
                "spread": "25%",
                "ignition_risk": 1,
                "stoking_risk": 3,
                "suspicion": 3,
                "advice": "Great as starter, insurance jobs, and small fires. Increases momentum in single area."
        },
        "Saltpetre": {
                "type": "Solid",
                "intensity": "31.25%",
                "intensity_abs": 10,
                "momentum": "HIGH",
                "momentum_abs": 6,
                "spread": "0%",
                "ignition_risk": 3,
                "stoking_risk": 1,
                "suspicion": 3,
                "advice": "Increases intensity by 25% of current intensity in single area."
        },
        "Magnesium": {
                "type": "Solid",
                "intensity": "27.5%",
                "intensity_abs": 8,
                "momentum": "HIGH",
                "momentum_abs": 6,
                "spread": "0%",
                "ignition_risk": 3,
                "stoking_risk": 4,
                "suspicion": 10,
                "advice": "Halves dampening effectiveness and intensity decay from firefighters. Increases visibility."
        },
        "Thermite": {
                "type": "Solid",
                "intensity": "22.5%",
                "intensity_abs": 7,
                "momentum": "MID",
                "momentum_abs": 4,
                "spread": "0%",
                "ignition_risk": 3,
                "stoking_risk": 7,
                "suspicion": 7,
                "advice": "Best as starter for total destruction. Multiplies damage rate for each use."
        },
        "Oxygen": {
                "type": "Gaseous",
                "intensity": "20%",
                "intensity_abs": 6,
                "momentum": "LOW",
                "momentum_abs": 2,
                "spread": "65%",
                "ignition_risk": 2,
                "stoking_risk": 1,
                "suspicion": 1,
                "advice": "Terrible starter, excellent for stoking size 4-5. Increases intensity by 25% of current in all areas."
        },
        "Methane": {
                "type": "Gaseous",
                "intensity": "15.6%",
                "intensity_abs": 4,
                "momentum": "LOW",
                "momentum_abs": 1,
                "spread": "84%",
                "ignition_risk": 2,
                "stoking_risk": 3,
                "suspicion": -3,
                "advice": "Excellent spread for large targets. Lowers accumulated suspicion."
        },
        "Hydrogen": {
                "type": "Gaseous",
                "intensity": "14%",
                "intensity_abs": 4,
                "momentum": "LOW",
                "momentum_abs": 1,
                "spread": "100%",
                "ignition_risk": 2,
                "stoking_risk": 3,
                "suspicion": 1,
                "advice": "Averages intensity and momentum across all areas. Best for size 3-5 targets."
        }
};

    const IGNITERS = {
        "Lighter": {
                "suspicion": 1,
                "advice": "Standard igniter. Provides 2.5% intensity when stoking."
        },
        "Molotov": {
                "suspicion": 6,
                "advice": "Moderately high intensity/momentum to area with lowest intensity. Fixed crit rate."
        },
        "Windproof Lighter": {
                "suspicion": 1,
                "advice": "Enhanced lighter. Same base stats as Lighter but works in adverse conditions."
        },
        "Flamethrower": {
                "suspicion": 8,
                "advice": "High intensity/momentum randomly across areas. Riskiest ignition choice."
        }
};

    const DAMPENERS = {
        "Blanket": {
                "effect": "-25% Intensity",
                "advice": "High crit rate (approx 1 in 5). dangerous at low skill."
        },
        "Sand": {
                "effect": "Negative momentum",
                "advice": "Unlocked at CS60. Effective for controlled burns."
        },
        "Fire Extinguisher": {
                "effect": "Negative momentum",
                "advice": "Unlocked at CS90. Safer and as effective as sand."
        }
};

    const BUILDINGS = {
        "Bazaar": {
                "areas": 1,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Beach Hut": {
                "areas": 1,
                "response_time": 120,
                "rurality": 3,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Firework Store": {
                "areas": 1,
                "response_time": 60,
                "rurality": 2,
                "dps": null,
                "flammability": -1,
                "urgency": null
        },
        "Fishing Hut": {
                "areas": 1,
                "response_time": 480,
                "rurality": 5,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Forgery Workshop": {
                "areas": 1,
                "response_time": 480,
                "rurality": 5,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 1
        },
        "Hunting Lodge": {
                "areas": 1,
                "response_time": 480,
                "rurality": 5,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 1
        },
        "Lifeguard Hut": {
                "areas": 1,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "Mobile Home": {
                "areas": 1,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "Restroom": {
                "areas": 1,
                "response_time": 120,
                "rurality": 3,
                "dps": "0.4/s",
                "flammability": 1,
                "urgency": 6
        },
        "Self Storage Container": {
                "areas": 1,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 1
        },
        "Shack": {
                "areas": 1,
                "response_time": 240,
                "rurality": 4,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Tool Shed": {
                "areas": 1,
                "response_time": 120,
                "rurality": 3,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Yurt": {
                "areas": 1,
                "response_time": 120,
                "rurality": 3,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Adult Store": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Apartment": {
                "areas": 2,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Arcade": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Barbershop": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Bookies": {
                "areas": 2,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Bordello": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "Bungalow": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 2
        },
        "Cafe": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "Candle Shop": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 3
        },
        "Chiropractors Office": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Cleaning Agency": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 2
        },
        "Clock Tower": {
                "areas": 2,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Clothing Store": {
                "areas": 2,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Community Center": {
                "areas": 2,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Cottage": {
                "areas": 2,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 1
        },
        "Cyber Cafe": {
                "areas": 2,
                "response_time": 30,
                "rurality": 1,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Dental Surgery": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": null,
                "flammability": -1,
                "urgency": null
        },
        "Detective Agency": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Diner": {
                "areas": 2,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 1
        },
        "Drugs Lab": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "Flower Shop": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Funeral Parlor": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "Game Shop": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Gas Station": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 3
        },
        "Hair Salon": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Hardware Store": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "Homeless Camp": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Jewelry Store": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Lingerie Store": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Liquor Store": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Loanshark Office": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Mechanic Shop": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "Music Store": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Pharmacy": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Police Safehouse": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Printing Store": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 3
        },
        "Suburban Home": {
                "areas": 2,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 2
        },
        "Tattoo Parlor": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Toy Shop": {
                "areas": 2,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Travel Agent": {
                "areas": 2,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Art Gallery": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Bank": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Barn": {
                "areas": 3,
                "response_time": 0,
                "rurality": -1,
                "dps": null,
                "flammability": -1,
                "urgency": null
        },
        "Bowling Alley": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Car Showroom": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Car Wash": {
                "areas": 3,
                "response_time": 120,
                "rurality": 3,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 4
        },
        "Cinema": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 5
        },
        "Distillery": {
                "areas": 3,
                "response_time": 240,
                "rurality": 4,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Farmhouse": {
                "areas": 3,
                "response_time": 480,
                "rurality": 5,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 1
        },
        "Fire Station": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "0.4/s",
                "flammability": 1,
                "urgency": 6
        },
        "Furniture Store": {
                "areas": 3,
                "response_time": 120,
                "rurality": 3,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Grocery Store": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Gym": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Laboratory": {
                "areas": 3,
                "response_time": 480,
                "rurality": 5,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 1
        },
        "Lakehouse": {
                "areas": 3,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 1
        },
        "Law Firm": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Library": {
                "areas": 3,
                "response_time": 120,
                "rurality": 3,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Medical Center": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Motorcycle Club": {
                "areas": 3,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 1
        },
        "Newspaper Office": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Nightclub": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Office Block": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Penthouse": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Pest Control Hub": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Police Station": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Private Security": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Pub": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Recording Studio": {
                "areas": 3,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 1
        },
        "Restaurant": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Strip Club": {
                "areas": 3,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Subway": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Townhouse": {
                "areas": 3,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Ad Agency": {
                "areas": 4,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Arms Warehouse": {
                "areas": 4,
                "response_time": 240,
                "rurality": 4,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Bus Terminal": {
                "areas": 4,
                "response_time": 30,
                "rurality": 1,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 6
        },
        "Chemical Plant": {
                "areas": 4,
                "response_time": 480,
                "rurality": 5,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Church": {
                "areas": 4,
                "response_time": 120,
                "rurality": 3,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 2
        },
        "College": {
                "areas": 4,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Fertilizer Plant": {
                "areas": 4,
                "response_time": 480,
                "rurality": 5,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Hotel": {
                "areas": 4,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Luxury Villa": {
                "areas": 4,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 1
        },
        "Manor House": {
                "areas": 4,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 1
        },
        "Paper Mill": {
                "areas": 4,
                "response_time": 240,
                "rurality": 4,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Post Office": {
                "areas": 4,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Raceway": {
                "areas": 4,
                "response_time": 60,
                "rurality": 2,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 3
        },
        "Ranch": {
                "areas": 4,
                "response_time": 480,
                "rurality": 5,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 1
        },
        "Recycling Facility": {
                "areas": 4,
                "response_time": 240,
                "rurality": 4,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Slaughterhouse": {
                "areas": 4,
                "response_time": 240,
                "rurality": 4,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 1
        },
        "Supermarket": {
                "areas": 4,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 4
        },
        "Theater": {
                "areas": 4,
                "response_time": 60,
                "rurality": 2,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 3
        },
        "Warehouse": {
                "areas": 4,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 1
        },
        "Aircraft Hangar": {
                "areas": 5,
                "response_time": 480,
                "rurality": 5,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        },
        "Casino": {
                "areas": 5,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Castle": {
                "areas": 5,
                "response_time": 480,
                "rurality": 5,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 1
        },
        "Cruise Line": {
                "areas": 5,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Data Center": {
                "areas": 5,
                "response_time": 480,
                "rurality": 5,
                "dps": "0.4/s",
                "flammability": 1,
                "urgency": 1
        },
        "Electrical Substation": {
                "areas": 5,
                "response_time": 240,
                "rurality": 4,
                "dps": "0.4/s",
                "flammability": 1,
                "urgency": 4
        },
        "Factory": {
                "areas": 5,
                "response_time": 240,
                "rurality": 4,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 1
        },
        "Foundry": {
                "areas": 5,
                "response_time": 240,
                "rurality": 4,
                "dps": "0.8/s",
                "flammability": 2,
                "urgency": 1
        },
        "Hospital": {
                "areas": 5,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Palace": {
                "areas": 5,
                "response_time": 480,
                "rurality": 5,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 1
        },
        "Shopping Mall": {
                "areas": 5,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "Sports Arena": {
                "areas": 5,
                "response_time": 30,
                "rurality": 1,
                "dps": "1.6/s",
                "flammability": 4,
                "urgency": 5
        },
        "TV Studio": {
                "areas": 5,
                "response_time": 60,
                "rurality": 2,
                "dps": "1.2/s",
                "flammability": 3,
                "urgency": 5
        },
        "Waste Facility": {
                "areas": 5,
                "response_time": 480,
                "rurality": 5,
                "dps": "2/s",
                "flammability": 5,
                "urgency": 1
        }
};

    const JOBS = {
        "Smoke Out": {
                "location": "Shack",
                "reward": 20000,
                "evidence": null
        },
        "Cut to the Chase": {
                "location": "Shack",
                "reward": 90000,
                "evidence": null
        },
        "The Bad Samaritan": {
                "location": "Shack",
                "reward": 20000,
                "evidence": null
        },
        "Unpopular Mechanics": {
                "location": "Tool Shed",
                "reward": null,
                "evidence": null
        },
        "Eight Lives": {
                "location": "Tool Shed",
                "reward": 10000,
                "evidence": null
        },
        "Beach Bum": {
                "location": "Beach Hut",
                "reward": null,
                "evidence": null
        },
        "A Rash Decision": {
                "location": "Beach Hut",
                "reward": 19000,
                "evidence": null
        },
        "Naked Aggression": {
                "location": "Beach Hut",
                "reward": 20000,
                "evidence": null
        },
        "High Time": {
                "location": "Yurt",
                "reward": 10500,
                "evidence": null
        },
        "Smoke on the Water": {
                "location": "Fishing Hut",
                "reward": 10000,
                "evidence": null
        },
        "Bagged and Tagged": {
                "location": "Hunting Lodge",
                "reward": null,
                "evidence": null
        },
        "Hide and Seek": {
                "location": "Hunting Lodge",
                "reward": null,
                "evidence": null
        },
        "Pest Control": {
                "location": "Hunting Lodge",
                "reward": 40000,
                "evidence": null
        },
        "On Fire at the Box Office": {
                "location": "Hunting Lodge",
                "reward": null,
                "evidence": "Gaseous"
        },
        "Out With a Bang": {
                "location": "Mobile Home",
                "reward": 40000,
                "evidence": null
        },
        "Family Feud": {
                "location": "Mobile Home",
                "reward": null,
                "evidence": null
        },
        "Cooked and Burned": {
                "location": "Mobile Home",
                "reward": 50000,
                "evidence": "Ammonia"
        },
        "Hot Off the Press": {
                "location": "Mobile Home",
                "reward": null,
                "evidence": null
        },
        "Shielded From the Truth": {
                "location": "Forgery Workshop",
                "reward": null,
                "evidence": null
        },
        "Fire Sale": {
                "location": "Forgery Workshop",
                "reward": null,
                "evidence": null
        },
        "Smoldering Resentment": {
                "location": "Self Storage Container",
                "reward": 20000,
                "evidence": null
        },
        "Burned by Stupidity": {
                "location": "Self Storage Container",
                "reward": 68000,
                "evidence": null
        },
        "Bone of Contention": {
                "location": "Self Storage Container",
                "reward": null,
                "evidence": null
        },
        "Cooking the Books": {
                "location": "Drugs Lab",
                "reward": 40000,
                "evidence": null
        },
        "The Grass Ain't Greener": {
                "location": "Drugs Lab",
                "reward": 60000,
                "evidence": null
        },
        "For Closure": {
                "location": "Bungalow",
                "reward": 51000,
                "evidence": null
        },
        "That Place is History": {
                "location": "Bungalow",
                "reward": 80000,
                "evidence": null
        },
        "Burning Memory": {
                "location": "Bungalow",
                "reward": null,
                "evidence": null
        },
        "Open House": {
                "location": "Bungalow",
                "reward": null,
                "evidence": null
        },
        "Fan the Flames": {
                "location": "Cottage",
                "reward": null,
                "evidence": null
        },
        "A Hot Lead": {
                "location": "Cottage",
                "reward": 40000,
                "evidence": null
        },
        "Local Concerns": {
                "location": "Cottage",
                "reward": 40000,
                "evidence": null
        },
        "Dead Giveaway": {
                "location": "Cottage",
                "reward": 84000,
                "evidence": null
        },
        "Daddy's Girl": {
                "location": "Townhouse",
                "reward": null,
                "evidence": null
        },
        "A Problem Shared": {
                "location": "Townhouse",
                "reward": 125000,
                "evidence": null
        },
        "Loud and Clear": {
                "location": "Apartment",
                "reward": 125000,
                "evidence": null
        },
        "A Dirty Job": {
                "location": "Apartment",
                "reward": 74000,
                "evidence": null
        },
        "Burning Liability": {
                "location": "Apartment",
                "reward": null,
                "evidence": null
        },
        "Raze the Roof": {
                "location": "Apartment",
                "reward": null,
                "evidence": null
        },
        "Low Rent": {
                "location": "Apartment",
                "reward": null,
                "evidence": null
        },
        "Wet Behind the Ears": {
                "location": "Apartment",
                "reward": null,
                "evidence": null
        },
        "Hot Dog": {
                "location": "Apartment",
                "reward": null,
                "evidence": null
        },
        "Chasing Targets": {
                "location": "Suburban Home",
                "reward": 60000,
                "evidence": null
        },
        "Fight Fire With Fire": {
                "location": "Suburban Home",
                "reward": null,
                "evidence": null
        },
        "Cold Feet": {
                "location": "Suburban Home",
                "reward": 80000,
                "evidence": null
        },
        "Twisted Firestarter": {
                "location": "Suburban Home",
                "reward": 50000,
                "evidence": null
        },
        "In Your Debt": {
                "location": "Suburban Home",
                "reward": 130000,
                "evidence": null
        },
        "Political Firestorm": {
                "location": "Suburban Home",
                "reward": 55000,
                "evidence": null
        },
        "Heat the Rich": {
                "location": "Lakehouse",
                "reward": 70000,
                "evidence": null
        },
        "It's a Write Off": {
                "location": "Lakehouse",
                "reward": 145000,
                "evidence": null
        },
        "Burning Through Cash": {
                "location": "Lakehouse",
                "reward": null,
                "evidence": null
        },
        "Cleansed Through Fire": {
                "location": "Penthouse",
                "reward": null,
                "evidence": null
        },
        "Banking on It": {
                "location": "Penthouse",
                "reward": null,
                "evidence": "Stapler"
        },
        "Cut Corners": {
                "location": "Penthouse",
                "reward": null,
                "evidence": null
        },
        "Follow the Leader": {
                "location": "Luxury Villa",
                "reward": null,
                "evidence": "Gaseous"
        },
        "Cook it Rare": {
                "location": "Luxury Villa",
                "reward": null,
                "evidence": null
        },
        "Faction Fiction": {
                "location": "Luxury Villa",
                "reward": null,
                "evidence": null
        },
        "Off the Market": {
                "location": "Ranch",
                "reward": 145000,
                "evidence": null
        },
        "The Fire Chief": {
                "location": "Ranch",
                "reward": null,
                "evidence": null
        },
        "The Empyre Strikes Back": {
                "location": "Ranch",
                "reward": null,
                "evidence": null
        },
        "To the Manor Scorned": {
                "location": "Manor House",
                "reward": null,
                "evidence": null
        },
        "Kindling Spirits": {
                "location": "Manor House",
                "reward": 100000,
                "evidence": null
        },
        "Ash or Credit?": {
                "location": "Manor House",
                "reward": null,
                "evidence": null
        },
        "The Ashes of Empire": {
                "location": "Palace",
                "reward": null,
                "evidence": null
        },
        "Where There's a Will": {
                "location": "Castle",
                "reward": 120000,
                "evidence": null
        },
        "It Cuts Both Ways": {
                "location": "Barbershop",
                "reward": null,
                "evidence": null
        },
        "Hair Today...": {
                "location": "Hair Salon",
                "reward": null,
                "evidence": null
        },
        "Planted": {
                "location": "Flower Shop",
                "reward": null,
                "evidence": "Pele Charm"
        },
        "A Fungus Among Us": {
                "location": "Flower Shop",
                "reward": 58000,
                "evidence": null
        },
        "Point of No Return": {
                "location": "Travel Agent",
                "reward": 100000,
                "evidence": null
        },
        "The Plane Truth": {
                "location": "Travel Agent",
                "reward": null,
                "evidence": null
        },
        "Don't Hate the Player": {
                "location": "Game Shop",
                "reward": null,
                "evidence": null
        },
        "Second Hand Smoke": {
                "location": "Game Shop",
                "reward": null,
                "evidence": null
        },
        "Claim to Flame": {
                "location": "Adult Store",
                "reward": null,
                "evidence": null
        },
        "Oh God, Yes!": {
                "location": "Adult Store",
                "reward": null,
                "evidence": null
        },
        "The Male Gaze": {
                "location": "Lingerie Store",
                "reward": 90000,
                "evidence": null
        },
        "A Treat for the Tricked": {
                "location": "Candle Shop",
                "reward": 100000,
                "evidence": "Kabuki Mask"
        },
        "Rest in Peace": {
                "location": "Candle Shop",
                "reward": 30000,
                "evidence": null
        },
        "Child's Play": {
                "location": "Toy Shop",
                "reward": 44000,
                "evidence": null
        },
        "Blaze of Glory": {
                "location": "Toy Shop",
                "reward": 105000,
                "evidence": "Toothbrush"
        },
        "Crafty Devil": {
                "location": "Liquor Store",
                "reward": 83000,
                "evidence": null
        },
        "Cop Some Heat": {
                "location": "Liquor Store",
                "reward": 60000,
                "evidence": null
        },
        "Liquor on the Back Row": {
                "location": "Liquor Store",
                "reward": 50000,
                "evidence": null
        },
        "Swansong": {
                "location": "Music Store",
                "reward": null,
                "evidence": null
        },
        "The Savage Beast": {
                "location": "Music Store",
                "reward": 115000,
                "evidence": null
        },
        "Doxing Clever": {
                "location": "Cyber Cafe",
                "reward": null,
                "evidence": null
        },
        "Stink to High Heaven": {
                "location": "Cyber Cafe",
                "reward": null,
                "evidence": null
        },
        "Hot Pursuit": {
                "location": "Detective Agency",
                "reward": 70000,
                "evidence": null
        },
        "Turn up the Heat": {
                "location": "Detective Agency",
                "reward": null,
                "evidence": "Compass"
        },
        "A Black Mark": {
                "location": "Detective Agency",
                "reward": null,
                "evidence": null
        },
        "Back, Sack, and Crack": {
                "location": "Chiropractors Office",
                "reward": null,
                "evidence": null
        },
        "You're Fired!": {
                "location": "Law Firm",
                "reward": null,
                "evidence": "Lipstick"
        },
        "The Smoking Gun": {
                "location": "Law Firm",
                "reward": null,
                "evidence": null
        },
        "Under the Table": {
                "location": "Law Firm",
                "reward": null,
                "evidence": null
        },
        "Set 'Em Straight": {
                "location": "Ad Agency",
                "reward": null,
                "evidence": null
        },
        "From the Ashes": {
                "location": "Ad Agency",
                "reward": null,
                "evidence": null
        },
        "Gym'll Fix It": {
                "location": "Gym",
                "reward": null,
                "evidence": null
        },
        "Muscling In": {
                "location": "Gym",
                "reward": null,
                "evidence": "Syringe"
        },
        "Burning Calories": {
                "location": "Gym",
                "reward": null,
                "evidence": null
        },
        "Wedded to the Lie": {
                "location": "Strip Club",
                "reward": 100000,
                "evidence": null
        },
        "Dirty Money": {
                "location": "Strip Club",
                "reward": null,
                "evidence": null
        },
        "Pyro for Pornos": {
                "location": "Strip Club",
                "reward": null,
                "evidence": null
        },
        "Burnt Ends": {
                "location": "Restaurant",
                "reward": null,
                "evidence": null
        },
        "Fire Kills 99.9% of Bacteria": {
                "location": "Restaurant",
                "reward": null,
                "evidence": null
        },
        "Uber Heats": {
                "location": "Restaurant",
                "reward": null,
                "evidence": null
        },
        "Home and Dry": {
                "location": "Pub",
                "reward": 80000,
                "evidence": null
        },
        "The Declaration of Inebrience": {
                "location": "Pub",
                "reward": 100000,
                "evidence": null
        },
        "The Waiting Game": {
                "location": "Pub",
                "reward": null,
                "evidence": null
        },
        "Short Shelf Life": {
                "location": "Grocery Store",
                "reward": null,
                "evidence": null
        },
        "Hot Profit": {
                "location": "Grocery Store",
                "reward": null,
                "evidence": null
        },
        "Unspilled Beans": {
                "location": "Grocery Store",
                "reward": null,
                "evidence": null
        },
        "One Rotten Apple": {
                "location": "Grocery Store",
                "reward": null,
                "evidence": null
        },
        "Specter of Destruction": {
                "location": "Funeral Parlor",
                "reward": 100000,
                "evidence": "Elephant Statue"
        },
        "Body of Evidence": {
                "location": "Funeral Parlor",
                "reward": 70000,
                "evidence": null
        },
        "Beyond Repair": {
                "location": "Mechanic Shop",
                "reward": 57500,
                "evidence": null
        },
        "Like for Like": {
                "location": "Mechanic Shop",
                "reward": null,
                "evidence": null
        },
        "Disco Inferno": {
                "location": "Nightclub",
                "reward": null,
                "evidence": null
        },
        "Party Pooper": {
                "location": "Nightclub",
                "reward": 80000,
                "evidence": null
        },
        "Gentrifried": {
                "location": "Nightclub",
                "reward": null,
                "evidence": null
        },
        "Burn up the Dancefloor": {
                "location": "Nightclub",
                "reward": null,
                "evidence": null
        },
        "Sky High Prices": {
                "location": "Firework Store",
                "reward": 60000,
                "evidence": "Glitter Bomb"
        },
        "A Mug's Game": {
                "location": "Bazaar",
                "reward": 40000,
                "evidence": null
        },
        "Anon Starter": {
                "location": "Bazaar",
                "reward": 30000,
                "evidence": null
        },
        "Risky Business": {
                "location": "Bazaar",
                "reward": 70000,
                "evidence": null
        },
        "Bang For Your Buck": {
                "location": "Bazaar",
                "reward": 40000,
                "evidence": "Grenade"
        },
        "Clean Sweep": {
                "location": "Cleaning Agency",
                "reward": 100000,
                "evidence": null
        },
        "Out in the Wash": {
                "location": "Car Wash",
                "reward": null,
                "evidence": null
        },
        "Hot Trend": {
                "location": "Clothing Store",
                "reward": null,
                "evidence": null
        },
        "All Mouth and Trousers": {
                "location": "Clothing Store",
                "reward": null,
                "evidence": "Diamond Ring"
        },
        "Beat the Odds": {
                "location": "Private Security",
                "reward": null,
                "evidence": null
        },
        "Hire and Fire": {
                "location": "Private Security",
                "reward": null,
                "evidence": null
        },
        "Crisp Bills": {
                "location": "Printing Store",
                "reward": 50000,
                "evidence": null
        },
        "Hell Fire": {
                "location": "Bordello",
                "reward": 200000,
                "evidence": null
        },
        "Camera Tricks": {
                "location": "Bordello",
                "reward": 70000,
                "evidence": null
        },
        "Lover's Quarrel": {
                "location": "Bordello",
                "reward": null,
                "evidence": null
        },
        "Milk Milk, Lemonade": {
                "location": "Bordello",
                "reward": null,
                "evidence": null
        },
        "Always Read the Label": {
                "location": "Pharmacy",
                "reward": 105000,
                "evidence": null
        },
        "Stick to the Script": {
                "location": "Pharmacy",
                "reward": null,
                "evidence": null
        },
        "Burn Rubber": {
                "location": "Motorcycle Club",
                "reward": 89000,
                "evidence": "Mayan Statue"
        },
        "Raising Hell": {
                "location": "Motorcycle Club",
                "reward": null,
                "evidence": null
        },
        "Light Fingered": {
                "location": "Post Office",
                "reward": null,
                "evidence": null
        },
        "Hold Fire": {
                "location": "Post Office",
                "reward": null,
                "evidence": null
        },
        "Letter of the Law": {
                "location": "Post Office",
                "reward": null,
                "evidence": null
        },
        "Burning Ambition": {
                "location": "Office Block",
                "reward": null,
                "evidence": null
        },
        "Hostile Takeover": {
                "location": "Office Block",
                "reward": null,
                "evidence": null
        },
        "Workplace Burnout": {
                "location": "Office Block",
                "reward": null,
                "evidence": null
        },
        "Chance of Redemption": {
                "location": "Office Block",
                "reward": null,
                "evidence": null
        },
        "Sofa King Cheap": {
                "location": "Furniture Store",
                "reward": 100000,
                "evidence": null
        },
        "Hot Gossip": {
                "location": "Newspaper Office",
                "reward": null,
                "evidence": null
        },
        "Burn the Deck": {
                "location": "Casino",
                "reward": 125000,
                "evidence": null
        },
        "House Edge": {
                "location": "Casino",
                "reward": null,
                "evidence": null
        },
        "House of Cards": {
                "location": "Casino",
                "reward": null,
                "evidence": null
        },
        "Curtain Call": {
                "location": "Theater",
                "reward": null,
                "evidence": null
        },
        "Fire Burn and Cauldron Bubble": {
                "location": "Theater",
                "reward": 105000,
                "evidence": null
        },
        "Get Wrecked": {
                "location": "Distillery",
                "reward": 70000,
                "evidence": null
        },
        "Whiskey Business": {
                "location": "Distillery",
                "reward": null,
                "evidence": null
        },
        "Cooking Time": {
                "location": "Clock Tower",
                "reward": null,
                "evidence": null
        },
        "Ashes to Ancestors": {
                "location": "Farmhouse",
                "reward": 73000,
                "evidence": null
        },
        "Shaky Investment": {
                "location": "Farmhouse",
                "reward": null,
                "evidence": null
        },
        "Foul Play": {
                "location": "Sports Arena",
                "reward": null,
                "evidence": null
        },
        "Boxing Clever": {
                "location": "Sports Arena",
                "reward": null,
                "evidence": null
        },
        "A Burnt Child Dreads the Fire": {
                "location": "Warehouse",
                "reward": null,
                "evidence": null
        },
        "Going Viral": {
                "location": "Warehouse",
                "reward": null,
                "evidence": null
        },
        "Old School": {
                "location": "Warehouse",
                "reward": 69000,
                "evidence": null
        },
        "Lock, Stock, and Barrel": {
                "location": "Warehouse",
                "reward": null,
                "evidence": null
        },
        "Totally Armless": {
                "location": "Arms Warehouse",
                "reward": null,
                "evidence": null
        },
        "Smoke Without Fire": {
                "location": "Arms Warehouse",
                "reward": null,
                "evidence": null
        },
        "Holy Smokes": {
                "location": "Church",
                "reward": null,
                "evidence": null
        },
        "Carrying a Torch": {
                "location": "Church",
                "reward": 79000,
                "evidence": null
        },
        "Visions of the Savory": {
                "location": "Church",
                "reward": null,
                "evidence": "Family Picture"
        },
        "It's Not All White": {
                "location": "Paper Mill",
                "reward": 125000,
                "evidence": null
        },
        "Igniting Curiosity": {
                "location": "College",
                "reward": null,
                "evidence": "Sumo Doll"
        },
        "The Midnight Oil": {
                "location": "College",
                "reward": 100000,
                "evidence": null
        },
        "Searing Irony": {
                "location": "Hospital",
                "reward": null,
                "evidence": null
        },
        "Waist Not, Want Not": {
                "location": "Hospital",
                "reward": null,
                "evidence": null
        },
        "Make a Killing": {
                "location": "Hospital",
                "reward": null,
                "evidence": null
        },
        "Not a Leg to Stand on": {
                "location": "Hospital",
                "reward": null,
                "evidence": null
        },
        "Blown to High Heaven": {
                "location": "Gas Station",
                "reward": 90000,
                "evidence": null
        },
        "Hot on the Trail": {
                "location": "Bank",
                "reward": null,
                "evidence": null
        },
        "Smoke Screen": {
                "location": "Bank",
                "reward": null,
                "evidence": null
        },
        "Charcoal Sketch": {
                "location": "Art Gallery",
                "reward": null,
                "evidence": null
        },
        "The Devil's in the Details": {
                "location": "Art Gallery",
                "reward": 115000,
                "evidence": null
        },
        "Flame and Fortune": {
                "location": "TV Studio",
                "reward": null,
                "evidence": null
        },
        "Apart of the Problem": {
                "location": "Factory",
                "reward": null,
                "evidence": null
        },
        "The Fried Piper": {
                "location": "Factory",
                "reward": null,
                "evidence": null
        },
        "Playing With Fire": {
                "location": "Laboratory",
                "reward": 145000,
                "evidence": null
        },
        "Bald Faced Destruction": {
                "location": "Laboratory",
                "reward": null,
                "evidence": "Raw Ivory"
        },
        "Remote Possibility": {
                "location": "Subway",
                "reward": 100000,
                "evidence": null
        },
        "Last Lyft Home": {
                "location": "Subway",
                "reward": null,
                "evidence": null
        },
        "Stop, Drop and Lol": {
                "location": "Fire Station",
                "reward": null,
                "evidence": null
        },
        "Green With Envy": {
                "location": "Recycling Facility",
                "reward": 90000,
                "evidence": null
        },
        "Burn Notice": {
                "location": "Police Safehouse",
                "reward": null,
                "evidence": null
        },
        "Medium Rare": {
                "location": "Slaughterhouse",
                "reward": null,
                "evidence": null
        },
        "Raze the Steaks": {
                "location": "Slaughterhouse",
                "reward": null,
                "evidence": null
        },
        "Third-Degree Burn": {
                "location": "Community Center",
                "reward": null,
                "evidence": null
        },
        "Burned Cookies": {
                "location": "Data Center",
                "reward": null,
                "evidence": null
        },
        "Cache and Burn": {
                "location": "Data Center",
                "reward": null,
                "evidence": null
        },
        "Bummed Out": {
                "location": "Homeless Camp",
                "reward": null,
                "evidence": null
        },
        "The Bolted Horse": {
                "location": "Barn",
                "reward": 105000,
                "evidence": null
        },
        "A Bitter Taste": {
                "location": "Dental Surgery",
                "reward": 80000,
                "evidence": null
        },
        "Checking Out": {
                "location": "Hotel",
                "reward": null,
                "evidence": null
        },
        "Landmark Decision": {
                "location": "Hotel",
                "reward": null,
                "evidence": null
        },
        "Spirit Level": {
                "location": "Hotel",
                "reward": null,
                "evidence": null
        },
        "Roast Beef": {
                "location": "Recording Studio",
                "reward": 130000,
                "evidence": null
        },
        "Plane and Simple": {
                "location": "Aircraft Hangar",
                "reward": 165000,
                "evidence": null
        },
        "Hot Under the Collar": {
                "location": "Foundry",
                "reward": null,
                "evidence": null
        },
        "Bugging Me": {
                "location": "Pest Control Hub",
                "reward": null,
                "evidence": "Gaseous"
        },
        "Finish Line": {
                "location": "Raceway",
                "reward": null,
                "evidence": null
        },
        "Read The Room": {
                "location": "Library",
                "reward": 100000,
                "evidence": null
        },
        "Fire in the Belly": {
                "location": "Library",
                "reward": 44000,
                "evidence": null
        },
        "Dine and Dash": {
                "location": "Diner",
                "reward": null,
                "evidence": null
        },
        "Hot Dinners": {
                "location": "Diner",
                "reward": null,
                "evidence": null
        },
        "Bright Spark": {
                "location": "Car Showroom",
                "reward": null,
                "evidence": null
        },
        "Emotional Wreck": {
                "location": "Car Showroom",
                "reward": 100000,
                "evidence": null
        },
        "Final Cut": {
                "location": "Cinema",
                "reward": null,
                "evidence": null
        },
        "Burn After Screening": {
                "location": "Cinema",
                "reward": null,
                "evidence": "Liquid"
        },
        "Strike While it's Hot": {
                "location": "Bowling Alley",
                "reward": null,
                "evidence": null
        },
        "Long Pig": {
                "location": "Cafe",
                "reward": 100000,
                "evidence": null
        },
        "Cold Brew Reality": {
                "location": "Cafe",
                "reward": null,
                "evidence": null
        },
        "Stroke of Fortune": {
                "location": "Hardware Store",
                "reward": 80000,
                "evidence": null
        },
        "Womb With a View": {
                "location": "Medical Center",
                "reward": 105000,
                "evidence": null
        },
        "Clinical Exposure": {
                "location": "Medical Center",
                "reward": null,
                "evidence": "Opium"
        },
        "See No Evil": {
                "location": "Medical Center",
                "reward": 90000,
                "evidence": null
        },
        "Mental Block": {
                "location": "Hospital",
                "reward": null,
                "evidence": null
        },
        "Wired for War": {
                "location": "Electrical Substation",
                "reward": null,
                "evidence": null
        },
        "Rock the Boat": {
                "location": "Cruise Line",
                "reward": null,
                "evidence": null
        },
        "Taking out the Trash": {
                "location": "Waste Facility",
                "reward": null,
                "evidence": "Hard Drive"
        },
        "Smoke Signals": {
                "location": "Waste Facility",
                "reward": null,
                "evidence": null
        },
        "Gay Frogs": {
                "location": "Chemical Plant",
                "reward": 40000,
                "evidence": null
        },
        "Boom Industry": {
                "location": "Fertilizer Plant",
                "reward": 90000,
                "evidence": null
        },
        "Piggy in the Middle": {
                "location": "Police Station",
                "reward": null,
                "evidence": null
        },
        "Final Markdown": {
                "location": "Supermarket",
                "reward": 105000,
                "evidence": null
        },
        "Marx & Sparks": {
                "location": "Supermarket",
                "reward": null,
                "evidence": null
        },
        "Supermarket Sweep": {
                "location": "Supermarket",
                "reward": null,
                "evidence": null
        },
        "Baewatch": {
                "location": "Lifeguard Hut",
                "reward": 18000,
                "evidence": null
        },
        "Mallrats": {
                "location": "Shopping Mall",
                "reward": null,
                "evidence": null
        },
        "Fire and Brimstone": {
                "location": "Shopping Mall",
                "reward": null,
                "evidence": null
        },
        "Beggars Can't be Choosers": {
                "location": "Bus Terminal",
                "reward": null,
                "evidence": null
        },
        "End of the Line": {
                "location": "Bus Terminal",
                "reward": null,
                "evidence": null
        },
        "Ring of Fire": {
                "location": "Jewelry Store",
                "reward": null,
                "evidence": null
        },
        "Needles to Say": {
                "location": "Tattoo Parlor",
                "reward": null,
                "evidence": null
        },
        "Marked for Salvation": {
                "location": "Tattoo Parlor",
                "reward": null,
                "evidence": null
        },
        "Insert Coin to Continue": {
                "location": "Arcade",
                "reward": null,
                "evidence": null
        },
        "Hot out of the Gate": {
                "location": "Bookies",
                "reward": null,
                "evidence": "Gold Tooth"
        },
        "Improving the Odds": {
                "location": "Bookies",
                "reward": 340000,
                "evidence": null
        },
        "Damned If You Don't": {
                "location": "Loanshark Office",
                "reward": null,
                "evidence": null
        },
        "Shit Happens": {
                "location": "Restroom",
                "reward": null,
                "evidence": null
        }
};

    const JOB_REQUIREMENTS = {
        "Insurance claim": "Suspicion must be kept low, use low suspicion accelerants like Oxygen, Saltpetre and Kerosene, or use Methane to remove suspicion.",
        "Total destruction": "Destruction must reach 100%.",
        "Minimum damage": "Destruction must go past X% (reaching X% is fine).",
        "Maximum damage": "Destruction must NOT go past X% (reaching X% is fine).",
        "Damage range": "Destruction must be between X% and Y% (both %s are inclusive).",
        "Plant evidence": "A miscellaneous item must be placed in advance. This will vary depending on the job.",
        "Specific accelerant": "Accelerants of a type different from the one specified will fail the job. Igniters and dampeners are allowed regardless.",
        "Accidental cause": "Same as insurance but less strict, keep suspicion low by using Oxygen, Saltpetre, etc.",
        "Highly suspicious": "Opposite of accidental cause, suspicion must be high. Using Gasoline and Magnesium is recommended.",
        "High visibility": "Visibility must be high. Using Magnesium and Diesel is recommended."
};

    const UNIQUE_TARGET_ADVICE = {
        "Shack - Cut to the Chase": {
                "unlock": "Contact: Chase Swindlehurst",
                "cs_required": 1,
                "advice": "Easy job, throw a few canisters of Gasoline and you'll be done."
        },
        "Bordello - Hell Fire": {
                "unlock": "Contact: Marvelous Mudenda",
                "cs_required": 5,
                "advice": "Similar to Chase's, drop 3-4 canisters of Gasoline and it should be fine."
        },
        "Bookies - Improving the Odds": {
                "unlock": "Contact: Denise David",
                "cs_required": 48,
                "advice": "Start with Diesel and Magnesium, then stoke with Diesel throughout."
        },
        "Clock Tower - Cooking Time": {
                "unlock": "Contact: Ethan McChad",
                "cs_required": 50,
                "advice": "Same as Denise's."
        },
        "Dental Surgery - A Bitter Taste": {
                "unlock": "Material: Oxygen",
                "cs_required": 5,
                "advice": "Plenty of Gasoline should do it."
        },
        "Barn - The Bolted Horse": {
                "unlock": "Material: Saltpetre",
                "cs_required": 10,
                "advice": "You'll need a lot of Oxygen, both for starting and for stoking."
        },
        "Gas Station - Blown to High Heaven": {
                "unlock": "Material: Diesel",
                "cs_required": 15,
                "advice": "This one's quite difficult. I suggest starting with Oxygen and dampening immediately afterwards, don't wait even a second."
        },
        "Firework Store - Sky High Prices": {
                "unlock": "Material: Magnesium",
                "cs_required": 20,
                "advice": "Gasoline + Saltpetre should do it, be ready to stoke with more Saltpetre. You'll also need a Glitter Bomb."
        },
        "Restroom - Shit Happens": {
                "unlock": "Material: Methane",
                "cs_required": 25,
                "advice": "You cannot fail this job even if you tried - and I tried really hard."
        },
        "Recording Studio - Roast Beef": {
                "unlock": "Material: Molotov Cocktail",
                "cs_required": 30,
                "advice": "Either 4 Diesel and get ready to dampen near the end, or 1 Gasoline and stoke with Oxygen twice right after."
        },
        "Aircraft Hangar - Plane and Simple": {
                "unlock": "Material: Kerosene",
                "cs_required": 40,
                "advice": "A combination of Diesel/Methane as openers followed by some Oxygen should do it."
        },
        "Foundry - Hot Under the Collar": {
                "unlock": "Material: Thermite",
                "cs_required": 50,
                "advice": "Low flammability but high rurality, do it however you'd like - time is on your side."
        },
        "Raceway - Finish Line": {
                "unlock": "Material: Sand",
                "cs_required": 60,
                "advice": "A small amount of Kerosene and a single Saltpetre as starters, then stoking with a tank of Methane did it for me. You can probably go even lower if you just want Sand."
        },
        "Homeless Camp - Bummed Out": {
                "unlock": "Material: Hydrogen",
                "cs_required": 70,
                "advice": "Kerosene x3 and stoking once or twice with Methane near the end will do it."
        },
        "Pest Control Hub - Bugging Me": {
                "unlock": "Material: Flamethrower",
                "cs_required": 80,
                "advice": "You will need a LOT of Oxygen for this one. Start the fire with 2 or 3, then stoke it near the end, you might need to do this a few times for total destruction."
        },
        "Undetermined": {
                "unlock": "Material: Fire Extinguisher",
                "cs_required": null,
                "advice": ""
        }
};

    const MOTIVE_LABELS = new Set(["Vendetta","Business","Emotional","Intimidation","Cover-up","Criminal","Superstition","Ideological","Redevelopment","Fraud"]);

    // HTML material name → cite.json key
    const NAME_MAP = {
        "Potassium Nitrate": "Saltpetre",
        "Magnesium Shavings": "Magnesium",
        "Oxygen Tank": "Oxygen",
        "Methane Tank": "Methane",
        "Hydrogen Tank": "Hydrogen",
        "Molotov Cocktail": "Molotov",
        "Fire Blanket": "Blanket"
};

    // ── CSS ───────────────────────────────────────────────────────────────

    const style = document.createElement('style');
    style.textContent = `
        .arson-helper-tooltip {
            display: none;
            position: fixed;
            z-index: 999999;
            background: #1a1a2e;
            color: #e0e0e0;
            border: 1px solid #444;
            border-radius: 6px;
            padding: 8px 12px;
            max-width: 320px;
            font-size: 12px;
            line-height: 1.5;
            font-family: Arial, Helvetica, sans-serif;
            pointer-events: none;
            box-shadow: 0 4px 12px rgba(0,0,0,0.5);
        }
        .arson-helper-tooltip.visible {
            display: block;
        }
        .arson-helper-tooltip .tt-title {
            font-weight: bold;
            color: #ffd700;
            margin-bottom: 4px;
            font-size: 13px;
        }
        .arson-helper-tooltip .tt-columns {
            display: flex;
            gap: 12px;
            margin-bottom: 6px;
        }
        .arson-helper-tooltip .tt-stats {
            display: grid;
            grid-template-columns: auto 1fr;
            gap: 2px 8px;
            margin-bottom: 6px;
        }
        .arson-helper-tooltip .tt-columns .tt-stats {
            margin-bottom: 0;
        }
        .arson-helper-tooltip .tt-label {
            color: #aaa;
        }
        .arson-helper-tooltip .tt-value {
            color: #fff;
        }
        .arson-helper-tooltip .tt-divider {
            border-top: 1px solid #333;
            margin: 4px 0;
        }
        .arson-helper-tooltip .tt-divider-strong {
            border-top: 2px solid #666;
            margin: 6px 0;
        }
        .arson-helper-tooltip .tt-stats-muted .tt-label,
        .arson-helper-tooltip .tt-stats-muted .tt-value {
            color: #888;
        }
        .arson-helper-tooltip .tt-advice {
            color: #8fc98f;
            font-style: italic;
            border-top: 1px solid #333;
            padding-top: 4px;
            margin-top: 4px;
        }
        .arson-helper-lightbulb {
            display: flex;
            align-items: center;
            justify-content: center;
            border: none;
            background: rgba(255, 255, 255, 0.08);
            cursor: pointer;
            font-size: 28px;
            padding: 4px 10px;
            border-radius: 6px;
            filter: grayscale(1);
            transition: background 0.15s;
        }
        .arson-helper-lightbulb:hover {
            background: rgba(255, 255, 255, 0.15);
        }
    `;
    document.head.appendChild(style);

    // ── Tooltip element ──────────────────────────────────────────────────

    const tooltip = document.createElement('div');
    tooltip.className = 'arson-helper-tooltip';
    document.body.appendChild(tooltip);

    function showTooltip(el, html) {
        tooltip.innerHTML = html;
        tooltip.classList.add('visible');
        positionTooltip(el);
    }

    function hideTooltip() {
        tooltip.classList.remove('visible');
    }

    function positionTooltip(el) {
        const rect = el.getBoundingClientRect();
        const tipRect = tooltip.getBoundingClientRect();
        let top = rect.bottom + 8;
        let left = rect.left + (rect.width / 2) - (tipRect.width / 2);

        // Clamp horizontal
        if (left < 4) left = 4;
        if (left + tipRect.width > window.innerWidth - 4) {
            left = window.innerWidth - tipRect.width - 4;
        }

        tooltip.style.top = top + 'px';
        tooltip.style.left = left + 'px';
    }

    function attachTooltip(el, html) {
        el.addEventListener('mouseenter', () => showTooltip(el, html));
        el.addEventListener('mouseleave', hideTooltip);
        el.addEventListener('click', hideTooltip);
    }

    // ── findClass (from SKILL.md) ────────────────────────────────────────

    const classCache = {};

    function findClass(prefix) {
        if (classCache[prefix]) return classCache[prefix];

        if (document.querySelector('.' + prefix)) {
            classCache[prefix] = prefix;
            return prefix;
        }

        const el = document.querySelector('[class*="' + prefix + '___"]');
        if (el) {
            const match = el.className.match(new RegExp(prefix + '___\\w+'));
            if (match) {
                classCache[prefix] = match[0];
                return match[0];
            }
        }

        for (const sheet of document.styleSheets) {
            try {
                for (const rule of sheet.cssRules || []) {
                    if (rule.selectorText && rule.selectorText.includes(prefix + '___')) {
                        const match = rule.selectorText.match(new RegExp(prefix + '___\\w+'));
                        if (match) {
                            classCache[prefix] = match[0];
                            return match[0];
                        }
                    }
                }
            } catch (e) {
                // Cross-origin stylesheets will throw
            }
        }

        return null;
    }

    // ── Material name parsing ────────────────────────────────────────────

    function parseMaterialName(ariaLabel) {
        if (!ariaLabel || ariaLabel === 'Item locked') return null;
        // Patterns: "Gasoline 238 owned", "Methane Tank 73 owned recommended",
        //           "Windproof Lighter Igniting is unavailable at this stage",
        //           "Blanket Dampening is unavailable at this stage"
        // Strip trailing info after the item name
        const match = ariaLabel.match(/^(.+?)(?:\s+\d+\s+owned(?:\s+(?:recommended|requested))?|\s+(?:Igniting|Dampening|Stoking|Spreading)\s+is\s+unavailable.*)$/);
        if (match) return match[1].trim();
        return null;
    }

    function lookupMaterial(name) {
        const key = NAME_MAP[name] || name;
        if (ACCELERANTS[key]) return { category: 'accelerant', data: ACCELERANTS[key], name: key };
        if (IGNITERS[key]) return { category: 'igniter', data: IGNITERS[key], name: key };
        if (DAMPENERS[key]) return { category: 'dampener', data: DAMPENERS[key], name: key };
        return null;
    }

    function buildMaterialTooltipHTML(info) {
        const d = info.data;
        let html = '<div class="tt-title">' + escapeHTML(info.name) + '</div>';

        if (info.category === 'accelerant') {
            html += '<div class="tt-columns"><div class="tt-stats">';
            html += colorStat('Intensity', d.intensity + ' (' + d.intensity_abs + '/10)', valueColor(d.intensity_abs, 0, 10));
            if (d.momentum === 'BEST') {
                html += colorStat('Momentum', d.momentum + ' (' + d.momentum_abs + '/10)', '#b44dff');
            } else {
                html += colorStat('Momentum', d.momentum + ' (' + d.momentum_abs + '/10)', valueColor(d.momentum_abs, 1, 6));
            }
            html += colorStat('Spread', d.spread, valueColor(parseFloat(d.spread), 0, 100));
            html += '</div><div class="tt-stats">';
            html += colorStat('Ignition Risk', String(d.ignition_risk), valueColor(d.ignition_risk, 0, 10));
            html += colorStat('Stoking Risk', String(d.stoking_risk), valueColor(d.stoking_risk, 0, 10));
            html += colorStat('Suspicion', String(d.suspicion), valueColor(d.suspicion, 0, 10));
            html += '</div></div>';
        } else if (info.category === 'igniter') {
            html += '<div class="tt-stats">';
            html += colorStat('Suspicion', String(d.suspicion), valueColor(d.suspicion, 0, 10));
            html += '</div>';
        } else if (info.category === 'dampener') {
            html += '<div class="tt-stats">';
            html += stat('Effect', d.effect);
            html += '</div>';
        }
        html += '<div class="tt-advice">' + escapeHTML(d.advice) + '</div>';
        return html;
    }

    function stat(label, value) {
        return '<span class="tt-label">' + escapeHTML(label) + ':</span><span class="tt-value">' + escapeHTML(value) + '</span>';
    }

    function colorStat(label, value, color) {
        return '<span class="tt-label">' + escapeHTML(label) + ':</span><span class="tt-value" style="color:' + color + '">' + escapeHTML(value) + '</span>';
    }

    // grey (#aaa) → yellow (#ffd700) → red (#ff4444)
    function valueColor(val, min, max) {
        if (val < min) return '#8fc98f';
        const t = Math.max(0, Math.min(1, (val - min) / (max - min)));
        let r, g, b;
        if (t < 0.5) {
            const s = t * 2;
            r = Math.round(170 + 85 * s);
            g = Math.round(170 + 45 * s);
            b = Math.round(170 - 170 * s);
        } else {
            const s = (t - 0.5) * 2;
            r = 255;
            g = Math.round(215 - 147 * s);
            b = Math.round(68 - 68 * s);
        }
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }

    function urgencyColor(val) {
        if (val >= 6) return '#b44dff';
        if (val >= 5) return '#ff4444';
        if (val >= 4) return '#ffd700';
        return '#8fc98f';
    }

    function urgencyLabel(val) {
        if (val >= 6) return 'Very Urgent (use thermite)';
        if (val >= 5) return 'Urgent (tend closely or thermite)';
        if (val >= 4) return 'Tight (maybe thermite or magnesium)';
        if (val >= 3) return 'OK (no thermite needed)';
        if (val >= 2) return 'Low (plenty of wiggle room)';
        return 'Very Low (feel free to play around)';
    }

    function escapeHTML(str) {
        const div = document.createElement('div');
        div.textContent = str;
        return div.innerHTML;
    }

    // ── Unique target matching ───────────────────────────────────────────

    function findUniqueTarget(locationType, scenarioText) {
        const full = locationType + ' - ' + scenarioText;
        // Try "Location - Scenario" match (e.g. "Shack - Cut to the Chase")
        if (UNIQUE_TARGET_ADVICE[full]) return UNIQUE_TARGET_ADVICE[full];
        // Try "Location Scenario" without separator (e.g. "Bordello Hell Fire")
        const noSep = locationType + ' ' + scenarioText;
        if (UNIQUE_TARGET_ADVICE[noSep]) return UNIQUE_TARGET_ADVICE[noSep];
        return null;
    }

    function formatTime(seconds) {
        if (seconds < 60) return seconds + 's';
        var m = Math.floor(seconds / 60);
        var s = seconds % 60;
        return s ? m + 'm ' + s + 's' : m + 'm';
    }

    function buildJobTooltipHTML(scenarioText, locationType) {
        let html = '';
        const building = BUILDINGS[locationType];
        const job = JOBS[scenarioText];
        const unique = findUniqueTarget(locationType, scenarioText);

        // Building stats
        if (building) {
            html += '<div class="tt-title">' + escapeHTML(locationType) + '</div>';
            html += '<div class="tt-stats">';
            if (building.flammability >= 0) html += colorStat('Flammability', String(building.flammability), valueColor(building.flammability, 1, 5));
            if (building.urgency != null) html += colorStat('Urgency', building.urgency + ' - ' + urgencyLabel(building.urgency), urgencyColor(building.urgency));
            html += stat('Response', formatTime(building.response_time));
            html += '</div>';
        }

        // Job info
        if (job) {
            if (job.reward || job.evidence) {
                html += '<div class="tt-divider"></div>';
                html += '<div class="tt-stats tt-stats-muted">';
                if (job.reward) html += stat('Reward', '~$' + job.reward.toLocaleString());
                if (job.evidence) html += stat('Evidence', job.evidence);
                html += '</div>';
            }
        }

        // Unique target advice
        if (unique) {
            html += '<div class="tt-divider-strong"></div>';
            html += '<div class="tt-stats">';
            html += stat('Unlock', unique.unlock);
            html += stat('CS Required', unique.cs_required != null ? String(unique.cs_required) : 'Unknown');
            html += '</div>';
            if (unique.advice) {
                html += '<div class="tt-advice">' + escapeHTML(unique.advice) + '</div>';
            }
        }

        return html;
    }

    // ── doUpdate ─────────────────────────────────────────────────────────

    function doUpdate() {
        if (isUpdating) return;
        isUpdating = true;
        try {
            processRequestIcons();
            processMaterialButtons();
            processScenarios();
        } finally {
            isUpdating = false;
        }
    }

    function processRequestIcons() {
        const cls = findClass('requestIcon');
        if (!cls) return;
        const icons = document.querySelectorAll('div[role="img"].' + cls);
        for (const icon of icons) {
            if (icon.dataset.arsonHelper) continue;
            icon.dataset.arsonHelper = '1';
            const label = icon.getAttribute('aria-label');
            if (!label || MOTIVE_LABELS.has(label)) continue;
            // Strip " required" suffix to get the key
            const key = label.replace(/ (?:required|requested)$/, '');
            const advice = JOB_REQUIREMENTS[key];
            if (advice) {
                const html = '<div class="tt-title">' + escapeHTML(key) + '</div><div class="tt-advice">' + escapeHTML(advice) + '</div>';
                attachTooltip(icon, html);
            }
        }
    }

    function processMaterialButtons() {
        const selectorCls = findClass('itemSelector');
        if (!selectorCls) return;
        const selectors = document.querySelectorAll('.' + selectorCls);
        if (!selectors.length) return;

        const wrapCls = findClass('itemCellWrap');
        if (!wrapCls) return;

        for (const selector of selectors) {
            const wraps = selector.querySelectorAll('.' + wrapCls);
            for (const wrap of wraps) {
                const btn = wrap.querySelector('button');
                if (!btn || btn.dataset.arsonHelper) continue;
                btn.dataset.arsonHelper = '1';
                const ariaLabel = btn.getAttribute('aria-label');
                const name = parseMaterialName(ariaLabel);
                if (!name) continue;
                const info = lookupMaterial(name);
                if (!info) continue;
                const html = buildMaterialTooltipHTML(info);
                attachTooltip(btn, html);
            }
        }
    }

    function processScenarios() {
        const scenarioCls = findClass('scenario');
        if (!scenarioCls) return;
        const scenarios = document.querySelectorAll('.' + scenarioCls);

        for (const scenario of scenarios) {
            if (scenario.dataset.arsonHelper) continue;
            scenario.dataset.arsonHelper = '1';

            const scenarioText = scenario.textContent.trim();
            // The sibling div above the scenario contains the location type
            const locationDiv = scenario.previousElementSibling;
            const locationType = locationDiv ? locationDiv.textContent.trim() : '';

            const html = buildJobTooltipHTML(scenarioText, locationType);
            if (!html) continue;

            // Find the desktopStatusSection sibling to insert before it
            const statusCls = findClass('desktopStatusSection');
            const sectionsCls = findClass('sections');
            const sectionsContainer = scenario.closest(sectionsCls ? '.' + sectionsCls : '.crime-option-sections');
            if (!sectionsContainer) continue;

            const statusSection = statusCls
                ? sectionsContainer.querySelector('.' + statusCls)
                : null;

            const bulb = document.createElement('div');
            bulb.className = 'arson-helper-lightbulb';
            bulb.textContent = '\u{1F4A1}';
            bulb.title = 'Job info';
            bulb.dataset.arsonHelper = '1';

            if (statusSection) {
                sectionsContainer.insertBefore(bulb, statusSection);
            } else {
                sectionsContainer.appendChild(bulb);
            }

            attachTooltip(bulb, html);
        }
    }

    // ── Mutation observer (from SKILL.md) ────────────────────────────────

    const enqueueUpdate = typeof window.requestAnimationFrame === 'function'
        ? (cb) => window.requestAnimationFrame(cb)
        : (cb) => setTimeout(cb, 50);
    let isUpdating = false;
    let updateScheduled = false;

    function scheduleUpdate(runImmediately = false) {
        if (runImmediately) {
            updateScheduled = false;
            doUpdate();
            return;
        }
        if (updateScheduled) return;
        updateScheduled = true;
        enqueueUpdate(() => {
            updateScheduled = false;
            doUpdate();
        });
    }

    const observer = new MutationObserver(() => scheduleUpdate());

    function startObserver() {
        observer.observe(document.body, { childList: true, subtree: true });
        scheduleUpdate(true);
    }

    if (document.body) {
        startObserver();
    } else {
        document.addEventListener('DOMContentLoaded', startObserver);
    }
})();