(function (root) {
  'use strict';

  const Danchi = root.Danchi = root.Danchi || {};
  const resident = (name, animation, prop, shirt, skin, build, extra) => ({
    name, animation, skeleton: animation, prop, speed: 1,
    appearance: Object.assign({ skin: skin || '#e8ad79', shirt, pants: '#344453', hair: '#4a3024', hat: null, build: build || 'normal', accessory: prop }, extra || {})
  });

  Danchi.DATA = {
    width: 960,
    height: 540,
    renderScale: 2,
    title: 'ベランダ団地シューティング',
    building: { x: 131, y: 75, w: 698, h: 368 },
    grid: { cols: 5, rows: 3, x: 150, y: 117, stepX: 138, stepY: 105, w: 110, h: 83 },
    caseRect: { x: 748, y: 455, w: 194, h: 69 },
    weapons: [
      { id: 'pistol', name: 'ピストル', label: 'PISTOL', key: '1', cooldown: 0.24, damage: 36, structuralImpact: 0.8, roomHeat: 1, radius: 0, unlockPhase: 0, color: '#f9d272', auto: false, shake: 0.65, marks: { count: 1, spread: 0, size: 2.3, sizeJitter: 0.6, shape: 'star' } },
      { id: 'shotgun', name: 'ショットガン', label: 'SHOTGUN', key: '2', cooldown: 0.58, damage: 76, structuralImpact: 1.35, roomHeat: 2, radius: 36, unlockPhase: 0, color: '#ffa652', auto: false, shake: 2.4, marks: { count: 7, spread: 21, size: 1.2, sizeJitter: 0.45, shape: 'pellet' } },
      { id: 'machinegun', name: 'マシンガン', label: 'MACHINE GUN', key: '3', cooldown: 0.095, damage: 27, structuralImpact: 1.1, roomHeat: 0.4, radius: 0, unlockPhase: 0, color: '#92d9ee', auto: true, shake: 1.1, marks: { count: 1, spread: 0, size: 1.65, sizeJitter: 0.45, shape: 'slash' } }
    ],
    phases: [
      { name: 'いつもの午後', label: 'QUIET AFTERNOON', threshold: 0, enemyInterval: 2.2, maxEnemies: 5, maxResidents: 3, enemyTypes: ['zombie', 'zombie', 'office'], unlockWeapon: 0, message: '緑の怪しい奴をクリック。1・2・3で好きな武器へ。' },
      { name: '少し騒がしい隣人', label: 'NEIGHBOR TROUBLE', threshold: 3500, enemyInterval: 1.75, maxEnemies: 6, maxResidents: 3, enemyTypes: ['zombie', 'office', 'runner', 'punk', 'punk'], unlockWeapon: 1, message: '走る奴にモヒカン。窓の向こうも大騒ぎ。' },
      { name: '団地、通常営業', label: 'BUSINESS AS USUAL', threshold: 14000, enemyInterval: 1.4, maxEnemies: 7, maxResidents: 2, enemyTypes: ['zombie', 'office', 'runner', 'punk', 'worker', 'dancer', 'brute', 'worker'], unlockWeapon: 2, message: '工事もダンスも通常営業。物干し泥棒にも注意。' },
      { name: 'だいたい全員のせい', label: 'TOTAL NEIGHBORHOOD CHAOS', threshold: 36000, enemyInterval: 1.1, maxEnemies: 8, maxResidents: 2, enemyTypes: ['zombie', 'office', 'runner', 'punk', 'worker', 'worker', 'dancer', 'dancer', 'brute', 'brute'], unlockWeapon: 2, message: '残業、工事、ダンス、大型の苦情。全員集合。' }
    ],
    scoring: {
      residentCharge: 12000, theftPenalty: 120, comboWindow: 4.25, comboStep: 3,
      maxMultiplier: 5, accidentBonus: 150, bossThreshold: 72000,
      comboMilestones: [3, 6, 9, 12],
      headshotMultiplier: 2, warningShot: 250
    },
    enemies: {
      zombie: { name: '普通ゾンビ', hp: 32, score: 100, w: 48, h: 58, lifetime: 14, animation: 'shamble', animationRate: 3.5, speed: 0.7, motion: { swayX: 7, frequencyX: 1.75, swayY: 0, frequencyY: 0, phaseY: 0 }, color: '#86bd61', appearance: { skin: '#86bd61', skinShadow: '#5d8748', skinLight: '#bcdf8a', skinDark: '#3e5f35', shirt: '#776f4f', pants: '#414a40', hair: '#4c5138', build: 'normal' } },
      runner: { name: 'せっかちゾンビ', hp: 27, score: 200, w: 46, h: 56, lifetime: 8, animation: 'run', animationRate: 7, speed: 2.3, motion: { swayX: 22, frequencyX: 5.75, swayY: 0, frequencyY: 0, phaseY: 0 }, color: '#9bcf63', appearance: { skin: '#9bcf63', skinShadow: '#6d9444', skinLight: '#d4e993', skinDark: '#496532', shirt: '#e86b4a', pants: '#51467a', hair: '#63516b', build: 'slim', hat: 'headband' } },
      brute: { name: '大型の苦情', hp: 142, score: 1000, w: 62, h: 75, lifetime: 18, animation: 'rage', animationRate: 3.5, speed: 0.8, motion: { swayX: 4, frequencyX: 2, swayY: 0, frequencyY: 0, phaseY: 0 }, color: '#ad8ace', appearance: { skin: '#ad8ace', skinShadow: '#7a609b', skinLight: '#d2b4e9', skinDark: '#51406b', shirt: '#e4dac0', pants: '#4b4560', hair: '#563b2d', build: 'large' } },
      office: { name: '残業ゾンビ', hp: 50, score: 160, w: 52, h: 62, lifetime: 14, animation: 'sway', animationRate: 2.3, speed: 0.6, motion: { swayX: 8, frequencyX: 1.2, swayY: 1.5, frequencyY: 2.4, phaseY: 0 }, color: '#86bd61', appearance: { skin: '#86bd61', skinShadow: '#5d8748', skinLight: '#bcdf8a', skinDark: '#3e5f35', shirt: '#35475e', pants: '#334153', hair: '#3b3935', build: 'normal', outfit: 'suit' } },
      worker: { name: '工事ゾンビ', hp: 108, score: 500, w: 60, h: 70, lifetime: 17, animation: 'stomp', animationRate: 3.3, speed: 0.85, motion: { swayX: 5, frequencyX: 2.2, swayY: 2, frequencyY: 4.4, phaseY: 0 }, color: '#9bcf63', appearance: { skin: '#9bcf63', skinShadow: '#6d9444', skinLight: '#d4e993', skinDark: '#496532', shirt: '#dc8b38', pants: '#4b555a', hair: '#665031', build: 'heavy', hat: 'hardhat', outfit: 'safety' } },
      punk: { name: 'モヒカンゾンビ', hp: 42, score: 260, w: 56, h: 64, lifetime: 9, animation: 'prowl', animationRate: 8.2, speed: 2.6, motion: { swayX: 26, frequencyX: 6.5, swayY: 0, frequencyY: 0, phaseY: 0 }, color: '#ad8ace', appearance: { skin: '#ad8ace', skinShadow: '#7a609b', skinLight: '#d2b4e9', skinDark: '#51406b', shirt: '#363445', pants: '#413543', hair: '#e174c2', build: 'slim', hairstyle: 'mohawk', outfit: 'leather' } },
      dancer: { name: 'ダンサーゾンビ', hp: 60, score: 350, w: 64, h: 62, lifetime: 12, animation: 'dance', animationRate: 6.5, speed: 1.7, motion: { swayX: 16, frequencyX: 3.5, swayY: 6, frequencyY: 5.5, phaseY: 1.2 }, color: '#a67bc3', appearance: { skin: '#a67bc3', skinShadow: '#75558f', skinLight: '#cda8e5', skinDark: '#4c385f', shirt: '#447fc2', pants: '#d6dce7', hair: '#3a3551', build: 'normal', hat: 'headphones', outfit: 'tracksuit' } },
      intruder: { name: '物干し泥棒', hp: 70, score: 300, w: 48, h: 64, lifetime: 13, animation: 'climb', speed: 1.2, color: '#72b285', appearance: { skin: '#72b285', skinShadow: '#4c7f60', skinLight: '#a4d8a7', skinDark: '#315940', shirt: '#6e68a3', pants: '#343b56', hair: '#28283b', hat: 'beanie', build: 'slim' } },
      boss: { name: '管理外の巨大クレーマー', hp: 2400, score: 5000, w: 144, h: 134, animation: 'rage', speed: 0.7, color: '#a67bc3', appearance: { skin: '#a67bc3', skinShadow: '#75558f', skinLight: '#cda8e5', skinDark: '#4c385f', shirt: '#eee0c9', pants: '#423c4d', hair: '#594031', build: 'large' } }
    },
    residents: {
      bbq: resident('BBQ男', 'work', 'bbq', '#f2ebd0', '#ecb082', 'heavy', { hair: '#523128' }),
      smoker: resident('一服男', 'relax', 'beer', '#6f9fac', '#d89f71', 'slim'),
      repair: resident('室外機修理男', 'work', 'tools', '#edaa4b', '#dca678', 'normal', { hat: 'cap' }),
      antenna: resident('アンテナ男', 'trouble', 'antenna', '#82a398', '#e9b38a', 'slim', { hair: '#d6d0b6' }),
      pigeon: resident('鳩おじさん', 'carry', 'pigeon', '#c09683', '#e5b28c', 'heavy', { hair: '#c9c4b2' }),
      bicycle: resident('自転車整備男', 'work', 'bike', '#c85842', '#d59466', 'normal', { hat: 'cap' }),
      gardener: resident('植木男', 'carry', 'watering', '#769b52', '#dca678', 'normal', { hat: 'straw' }),
      diy: resident('謎DIY男', 'trouble', 'hammer', '#e1ad51', '#e8ad79', 'normal', { hair: '#733c22' }),
      shrine: resident('謎の祭壇男', 'ritual', 'altar', '#937197', '#cea28b', 'slim', { hair: '#251e2b' }),
      binoculars: resident('双眼鏡男', 'relax', 'binoculars', '#658caa', '#e3b58b', 'normal', { hat: 'cap' }),
      coffee: resident('コーヒー男', 'relax', 'cup', '#5b9a74', '#e1aa7b', 'slim', { accessory: 'glasses' }),
      boxes: resident('引っ越さない引っ越し男', 'carry', 'box', '#bd764d', '#dfb595', 'heavy'),
      camera: resident('スクープ待ちのカメラ男', 'work', 'camera', '#c78e39', '#d6a777', 'normal', { hat: 'cap', accessory: 'glasses' }),
      reader: resident('読書に夢中のお姉さん', 'relax', 'book', '#c06493', '#efd0ac', 'slim', { hair: '#442e35' }),
      phone: resident('実況配信の青年', 'trouble', 'phone', '#4aa8aa', '#d9a987', 'slim', { hair: '#5d486f', hat: 'headband' }),
      radio: resident('ラジオ体操のおじさん', 'ritual', 'radio', '#cf674c', '#dbaf89', 'heavy', { hair: '#a7a394' }),
      fishing: resident('ベランダ釣り師', 'carry', 'fishing', '#729b7f', '#bc8967', 'normal', { hat: 'straw' }),
      painter: resident('風景画のおばさん', 'work', 'paint', '#f1df93', '#e9b58c', 'heavy', { hair: '#cbc7b8', hat: 'beret' }),
      newspaper: resident('新聞に怒るおじいさん', 'trouble', 'newspaper', '#9792b2', '#d6af8e', 'slim', { hair: '#e3ddcf', accessory: 'glasses' }),
      umbrella: resident('晴天でも傘の人', 'carry', 'umbrella', '#5583bd', '#ecc09b', 'normal', { hair: '#342833' })
    },
    props: {
      window: { name: '窓ガラス交換', hp: 108, cost: 24000, score: 25, w: 94, h: 61, color: '#9bc4cd', material: 'glass', falls: false, panes: 2, paneInset: 2, paneGap: 4, chipRadius: 9, maxImpacts: 8, shards: { crack: 3, chip: 12, shatter: 28 } },
      ac: { name: '室外機破損', hp: 68, cost: 72000, score: 50, w: 26, h: 23, color: '#abb6b1', material: 'metal', falls: true },
      pot: { name: '植木鉢破損', hp: 1, cost: 6500, score: 25, w: 17, h: 24, color: '#bd693e', material: 'clay', falls: true },
      bbq: { name: 'BBQコンロ転倒', hp: 58, cost: 18000, score: 50, w: 31, h: 24, color: '#464347', material: 'metal', burns: true },
      rail: { name: 'ベランダ手すり修理', hp: 105, cost: 43000, score: 25, w: 110, h: 24, color: '#4c646d', material: 'metal', falls: false }
    },
    balconyTemplates: [
      { id: 'cookout', resident: 'bbq', props: [{ type: 'bbq', dx: 74, dy: 36 }, { type: 'pot', dx: 2, dy: 35 }], decoration: ['chair', 'table', 'bottle', 'laundry'] },
      { id: 'coffee', resident: 'coffee', props: [{ type: 'pot', dx: 88, dy: 35 }], decoration: ['chair', 'table', 'cup', 'books', 'curtain'] },
      { id: 'repair', resident: 'repair', props: [{ type: 'ac', dx: 81, dy: 3 }], decoration: ['toolbox', 'shelf', 'clothesline'] },
      { id: 'garden', resident: 'gardener', props: [{ type: 'pot', dx: 4, dy: 35 }, { type: 'pot', dx: 87, dy: 35 }], decoration: ['watering', 'shelf', 'laundry'] },
      { id: 'hobby', resident: 'diy', props: [{ type: 'ac', dx: 81, dy: 3 }], decoration: ['toolbox', 'box', 'tv', 'garbage'] },
      { id: 'smoking', resident: 'smoker', props: [{ type: 'bbq', dx: 5, dy: 36 }], decoration: ['chair', 'ashtray', 'bottle', 'futon'] },
      { id: 'bike', resident: 'bicycle', props: [{ type: 'pot', dx: 89, dy: 35 }], decoration: ['bike', 'toolbox', 'clothesline'] },
      { id: 'odd', resident: 'shrine', props: [{ type: 'pot', dx: 2, dy: 35 }], decoration: ['altar', 'shelf', 'candles', 'curtain'] },
      { id: 'moving', resident: 'boxes', props: [{ type: 'ac', dx: 81, dy: 3 }], decoration: ['box', 'fridge', 'garbage', 'laundry'] },
      { id: 'rooftop', resident: 'antenna', props: [{ type: 'pot', dx: 87, dy: 35 }], decoration: ['antenna', 'binoculars', 'pigeon', 'chair'] }
    ],
    bulletMarks: {
      maxCount: 600,
      surfaceBounds: { x: 131, y: 78, w: 698, h: 354 },
      opening: { dx: 8, dy: 1, w: 94, h: 74, frameWidth: 3, mullionDx: 53, mullionWidth: 4 },
      hole: { centreDy: 35, radius: 71 },
      foregroundEdge: [{ x: 0, y: 431 }, { x: 174, y: 428 }, { x: 715, y: 494 }, { x: 960, y: 478 }],
      foregroundTowel: { x: 135, y: 428, w: 63, h: 64 },
      rail: { topHeight: 3, bottomOffset: 3, bottomHeight: 2, barCount: 12, barInset: 3, barWidth: 2 },
      propInsets: { ac: 1, potBodyStart: 0.66, bbqBodyStart: 0.12, bbqBodyEnd: 0.61 }
    },
    roomFire: {
      threshold: 8, bounds: { dx: 10, dy: 4, w: 90, h: 68 },
      burningDuration: 3, spreadingDuration: 5, smokeDuration: 6,
      interiorCost: 98000, contentsCost: 56000,
      particleInterval: 0.11, maxShotDamage: 10000,
      spreadPropTypes: ['window'], smokeResidue: 0.22
    },
    dynamite: {
      offsetX: 88, offsetY: -95, w: 24, h: 36,
      cost: 1200000,
      shake: 8, flash: 0.65, particles: 110,
      neighbours: [{ dc: 1, dr: 0 }, { dc: 0, dr: 1 }],
      damagePropTypes: ['window', 'rail']
    },
    bossFight: {
      rageDuration: 18, bombFlightDuration: 1.1, bombScorePenalty: 25000, headshotDamageMultiplier: 2
    },
    structure: {
      maxHp: 36000, roomIgnitionDamage: 180, roomSpreadDamage: 420,
      bbqFireDamage: 90, dynamiteDamage: 1800,
      rebuildCost: 12000000, collapseDuration: 6.5,
      floorImpactTimes: [0.65, 1.35, 2.1], settledTime: 4,
      warningRatios: [0.5, 0.25, 0.1],
      warningMessages: ['建物がきしんでいる……。', '建物の耐久が残りわずか！', '建物が限界！　撃ち続けると全壊する。']
    },
    tuning: {
      maxDt: 0.05, maxParticles: 340, maxFloaters: 35, maxTracers: 35,
      firstEnemyDelay: 0.75, firstResidentDelay: 0.3, residentInterval: 4.4,
      residentLifetime: 15, residentReaction: 1.85, residentSpawnCooldown: 2.5, warningRetreatDuration: 0.3,
      enemySpawnJitter: 0.15, maxActors: 12, enemyFadeTime: 0.43,
      firstIntruderDelay: 11, intruderInterval: 20, intruderJourney: 9.5, intruderLeaveTime: 1.7,
      fallChance: 0.34, knockChance: 0.19, fireChance: 0.48,
      fallDuration: 0.62, fireDuration: 4.5, fireDelay: 0.85, maxChainDepth: 3,
      quietDuration: 1.6, rocketFlight: 0.68, endingDuration: 7.18,
      wallRepairCost: 86000, laundryRepairCost: 12000, finalRepairCost: 1800000,
      messageDuration: 4.2, maxDamageState: 3,
      particleGravity: 125, particleLife: 0.95,
      theftItems: ['洗濯物', 'ピザ', 'テレビのリモコン', '植木鉢'],
      residentBarks: ['おい！', 'こっち見るな！', '豆じゃないぞ！', '管理人を呼ぶぞ！', 'コーヒーが！'],
      bossBarks: ['建物への攻撃をやめろ！', '壁を撃つな！　修繕費が！', '住人の部屋を壊すな！', '狙うならこっちだ！'],
      bossSpeechDuration: 2.8, bossSpeechInterval: 3.6,
      intruderRoute: [{ x: 731, y: 294 }, { x: 690, y: 328 }, { x: 636, y: 375 }, { x: 569, y: 439 }, { x: 469, y: 512 }]
    }
  };
})(globalThis);
