code:
/**
 * @typedef {object} itemFS
 * @property {FC.FutureSociety} [unlocks] Automatically unlocked with this FS.
 * @property {Set<FC.FutureSociety>} [loves] FS loves to see this outfit.
 * @property {Set<FC.FutureSociety>} [tolerates] FS tolerates this outfit.
 * @property {Set<FC.FutureSociety>} [hates] FS hates to see this outfit.
 */

/**
 * @typedef {object} clothingDescription
 * @property {function(App.Entity.SlaveState):string} [summary] General description of the outfit, tailored to the slave, but not hyper focused on a body part like boobs or butt.
 * @property {function(App.Entity.SlaveState):string} [upperFace]
 * @property {function(App.Entity.SlaveState):string} [hStyle]
 * @property {function(App.Entity.SlaveState):string} [earPiercing]
 * @property {function(App.Entity.SlaveState):string} [corsetPiercing]
 * @property {function(App.Entity.SlaveState):string} [bellyImplant]
 * @property {function(App.Entity.SlaveState):string} [belly]
 * @property {function(App.Entity.SlaveState):string} [inflation]
 * @property {function(App.Entity.SlaveState):string} [crotch]
 * @property {function(App.Entity.SlaveState):string} [butt]
 * @property {function(App.Entity.SlaveState):string} [buttplug]
 * @property {function(App.Entity.SlaveState):string} [clothingCorset]
 * @property {function(App.Entity.SlaveState):string} [boobs]
 */

/**
 * @typedef {object} clothes
 * @property {string} name
 * @property {itemFS} [fs]
 * @property {boolean} [requirements]
 * @property {0|1|2|3|4} [exposure] 0: Modest, 1: Acceptable, 2: Slutty, 3: Humiliating (exposes genitals), 4: Might as well be nude
 * @property {boolean} [harsh]
 * @property {boolean} [topless]
 * @property {boolean} [fuckdoll]
 * @property {string} [note]
 * @property {clothingDescription} [desc]
 */

/** @type {Map.<FC.Clothes, clothes>} The string here will be what is applied to the relevant slave property. Slave.clothes = "a bunny outfit", not "Bunny outfit".*/
App.Data.clothes = (new Map())
	.set("a Fuckdoll suit",
		{
			name: "Fuckdoll suit",
			exposure: 3,
			fuckdoll: true
		}
	)
	.set("attractive lingerie for a pregnant woman",
		{
			name: "Maternity lingerie",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSIntellectualDependency", "FSRepopulationFocus"]),
			},
			get requirements() { return V.boughtItem.clothing.maternityLingerie === 1; },
			exposure: 2
		}
	)
	.set("a bunny outfit",
		{
			name: "Bunny outfit",
			fs: {
				unlocks: "FSGenderFundamentalist",
				loves: new Set(["FSGenderFundamentalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.bunny === 1; },
			exposure: 1
		}
	)
	.set("body oil",
		{
			name: "Body oil",
			fs: {
				unlocks: "FSPhysicalIdealist",
				loves: new Set(["FSPhysicalIdealist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.oil === 1; },
			exposure: 4
		}
	)
	.set("a chattel habit",
		{
			name: "Chattel habit",
			fs: {
				unlocks: "FSChattelReligionist",
				loves: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.habit === 1; },
			exposure: 3
		}
	)
	.set("conservative clothing",
		{
			name: "Conservative clothing",
			fs: {
				unlocks: "FSPaternalist",
				loves: new Set(["FSPaternalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.conservative === 1; },
			exposure: 0
		}
	)
	.set("harem gauze",
		{
			name: "Harem gauze",
			fs: {
				unlocks: "FSArabianRevivalist",
				loves: new Set(["FSArabianRevivalist"]),
			},
			get requirements() { return V.boughtItem.clothing.harem === 1; },
			exposure: 1
		}
	)
	.set("a huipil",
		{
			name: "Huipil",
			fs: {
				unlocks: "FSAztecRevivalist",
				loves: new Set(["FSAztecRevivalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.huipil === 1; },
			exposure: 0
		}
	)
	.set("a kimono",
		{
			name: "Kimono",
			fs: {
				unlocks: "FSEdoRevivalist",
				loves: new Set(["FSEdoRevivalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return (V.boughtItem.clothing.kimono === 1 || V.continent === "Japan"); },
			exposure: 0
		}
	)
	.set("a maternity dress",
		{
			name: "Maternity dress",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"]),
			},
			get requirements() { return V.boughtItem.clothing.maternityDress === 1; },
			exposure: 0,
		}
	)
	.set("a slutty qipao",
		{
			name: "Qipao (slutty)",
			fs: {
				unlocks: "FSChineseRevivalist",
				loves: new Set(["FSChineseRevivalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.qipao === 1; },
			exposure: 2
		}
	)
	.set("a long qipao",
		{
			name: "Qipao (long)",
			fs: {
				unlocks: "FSChineseRevivalist",
				loves: new Set(["FSChineseRevivalist"]),
			},
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("Imperial Plate",
		{
			name: "Imperial Plate",
			fs: {
				unlocks: "FSNeoImperialist",
				loves: new Set(["FSNeoImperialist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.imperialarmor === 1; },
			exposure: 0
		}
	)
	.set("a tight Imperial bodysuit",
		{
			name: "Imperial Bodysuit",
			fs: {
				unlocks: "FSNeoImperialist",
				loves: new Set(["FSNeoImperialist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.imperialsuit === 1; },
			exposure: 2
		}
	)
	.set("stretch pants and a crop-top",
		{
			name: "Stretch pants and a crop-top",
			fs: {unlocks: "FSHedonisticDecadence"},
			get requirements() { return V.boughtItem.clothing.lazyClothes === 1; },
			exposure: 0
		}
	)
	.set("a toga",
		{
			name: "Toga",
			fs: {
				unlocks: "FSRomanRevivalist",
				loves: new Set(["FSRomanRevivalist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.toga === 1; },
			exposure: 1
		}
	)
	.set("Western clothing",
		{
			name: "Western clothing",
			fs: {
				unlocks: "FSPastoralist",
				loves: new Set(["FSPastoralist"]),
			},
			get requirements() { return V.boughtItem.clothing.western === 1; },
			exposure: 3
		}
	)
	.set("a courtesan dress",
		{
			name: "Courtesan dress",
			fs: {
				unlocks: "FSSlaveProfessionalism",
				loves: new Set(["FSSlaveProfessionalism"]),
			},
			get requirements() { return V.boughtItem.clothing.courtesan === 1; },
			exposure: 1
		}
	)
	.set("a bimbo outfit",
		{
			name: "Bimbo outfit",
			fs: {
				unlocks: "FSIntellectualDependency",
				loves: new Set(["FSIntellectualDependency"]),
			},
			get requirements() { return V.boughtItem.clothing.bimbo === 1; },
			exposure: 2
		}
	)
	.set("petite admi outfit",
		{
			name: "Petite admi outfit",
			fs: {
				unlocks: "FSPetiteAdmiration",
				loves: new Set(["FSPetiteAdmiration"]),
			},
			get requirements() { return V.boughtItem.clothing.petite === 1; },
			exposure: 0
		}
	)
	.set("battlearmor",
		{
			name: "Battlearmor",
			get requirements() { return V.boughtItem.clothing.military === 1; },
			exposure: 0
		}
	)
	.set("a military uniform",
		{
			name: "Military uniform",
			fs: {
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.military === 1; },
			exposure: 0
		}
	)
	.set("a red army uniform",
		{
			name: "Red Army uniform",
			get requirements() { return V.boughtItem.clothing.military === 1; },
			exposure: 0
		}
	)
	.set("battledress",
		{
			name: "Battledress",
			get requirements() { return V.boughtItem.clothing.military === 1; },
			exposure: 0
		}
	)
	.set("a biyelgee costume",
		{
			name: "Biyelgee costume",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("a dirndl",
		{
			name: "Dirndl",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("lederhosen",
		{
			name: "Lederhosen",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("a mounty outfit",
		{
			name: "Mounty outfit",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("a hanbok",
		{
			name: "Hanbok",
			get requirements() { return V.boughtItem.clothing.cultural === 1; },
			exposure: 0
		}
	)
	.set("a burqa",
		{
			name: "Burqa",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; },
			exposure: 0
		}
	)
	.set("a niqab and abaya",
		{
			name: "Niqab and abaya",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.middleEastern === 1 || V.continent === "the Middle East"; },
			exposure: 0
		}
	)
	.set("a hijab and blouse",
		{
			name: "Hijab and blouse",
			fs: {
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return (V.boughtItem.clothing.conservative === 1 || V.continent === "the Middle East"); },
			exposure: 0
		}
	)
	.set("a burkini",
		{
			name: "Burkini",
			get requirements() { return V.boughtItem.clothing.swimwear === 1 && (V.boughtItem.clothing.swimwear === 1 || V.continent === "the Middle East"); },
			exposure: 1
		}
	)
	.set("a Santa dress",
		{
			name: "Santa dress",
			get requirements() { return V.boughtItem.clothing.costume === 1; },
			exposure: 2
		}
	)
	.set("a klan robe",
		{
			name: "Klan robe",
			get requirements() { return V.boughtItem.clothing.pol === 1; },
			exposure: 0
		}
	)
	.set("a slutty klan robe",
		{
			name: "Slutty klan robe",
			get requirements() { return V.boughtItem.clothing.pol === 1; },
			exposure: 2
		}
	)
	.set("a schutzstaffel uniform",
		{
			name: "Schutzstaffel uniform",
			get requirements() { return V.boughtItem.clothing.pol === 1; },
			exposure: 0
		}
	)
	.set("a slutty schutzstaffel uniform",
		{
			name: "Slutty schutzstaffel uniform",
			get requirements() { return V.boughtItem.clothing.pol === 1; },
			exposure: 2
		}
	)
	.set("nice business attire",
		{
			name: "Nice business attire",
			get requirements() { return V.boughtItem.clothing.career === 1; },
			exposure: 0,
			fs: {
				loves: new Set(["FSMaturityPreferentialist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
		}
	)
	.set("a nice nurse outfit",
		{
			name: "Nurse (nice)",
			fs: {
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.career === 1; },
			exposure: 0
		}
	)
	.set("a police uniform",
		{
			name: "Police uniform",
			get requirements() { return V.boughtItem.clothing.career === 1; },
			exposure: 0
		}
	)
	.set("a nice maid outfit",
		{
			name: "Maid (nice)",
			get requirements() { return V.boughtItem.clothing.career === 1 || V.PC.career === "servant" || V.PC.career === "handmaiden" || V.PC.career === "child servant"; },
			exposure: 0,
			fs: {
				loves: new Set(["FSMaturityPreferentialist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
		}
	)
	.set("a ball gown",
		{
			name: "Ballgown",
			get requirements() { return V.boughtItem.clothing.dresses === 1; },
			exposure: 0
		}
	)
	.set("a gothic lolita dress",
		{
			name: "Gothic lolita dress",
			get requirements() { return V.boughtItem.clothing.dresses === 1; },
			exposure: 0
		}
	)
	.set("a cybersuit",
		{
			name: "Cybersuit",
			get requirements() { return V.boughtItem.clothing.bodysuits === 1; },
			exposure: 0
		}
	)
	.set("a latex catsuit",
		{
			name: "Latex catsuit",
			get requirements() { return V.boughtItem.clothing.bodysuits === 1; },
			exposure: 1
		}
	)
	.set("a button-up shirt and panties",
		{
			name: "Button-up shirt and panties",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("a button-up shirt",
		{
			name: "Button-up shirt",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("cutoffs",
		{
			name: "Cutoffs",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("jeans",
		{
			name: "Jeans",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2,
			topless: true
		}
	)
	.set("leather pants and a tube top",
		{
			name: "Leather pants and a tube top",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 1
		}
	)
	.set("leather pants",
		{
			name: "Leather pants",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2,
			topless: true
		}
	)
	.set("an oversized t-shirt",
		{
			name: "Oversized t-shirt",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("a sweater and cutoffs",
		{
			name: "Sweater and cutoffs",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 0
		}
	)
	.set("a sweater and panties",
		{
			name: "Sweater and panties",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("a sweater",
		{
			name: "Sweater",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("a t-shirt and jeans",
		{
			name: "T-shirt and jeans",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 0
		}
	)
	.set("a t-shirt and panties",
		{
			name: "T-shirt and panties",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("a t-shirt",
		{
			name: "T-shirt",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("a tank-top and panties",
		{
			name: "Tank-top and panties",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 2
		}
	)
	.set("a tank-top",
		{
			name: "Tank-top",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("a tube top",
		{
			name: "Tube top",
			get requirements() { return V.boughtItem.clothing.casual === 1; },
			exposure: 3
		}
	)
	.set("boyshorts",
		{
			name: "Boyshorts",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 2,
			topless: true
		}
	)
	.set("a bra",
		{
			name: "Bra",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 3
		}
	)
	.set("kitty lingerie",
		{
			name: "Kitty lingerie",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 2
		}
	)
	.set("panties and pasties",
		{
			name: "Panties and pasties",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 2
		}
	)
	.set("a skimpy loincloth",
		{
			name: "Skimpy loincloth",
			fs: {
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 3
		}
	)
	.set("a thong",
		{
			name: "Thong",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 3,
			topless: true
		}
	)
	.set("pasties",
		{
			name: "Pasties",
			get requirements() { return V.boughtItem.clothing.underwear === 1; },
			exposure: 3
		}
	)
	.set("leather pants and pasties",
		{
			name: "Leather pants and pasties",
			get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 2,
		}
	)
	.set("a t-shirt and thong",
		{
			name: "T-shirt and thong",
			get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 3,
		}
	)
	.set("a tube top and thong",
		{
			name: "Tube top and thong",
			get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 3,
		}
	)
	.set("an oversized t-shirt and boyshorts",
		{
			name: "Oversized t-shirt and boyshorts",
			get requirements() { return V.boughtItem.clothing.underwear === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 0,
		}
	)
	.set("sport shorts and a sports bra",
		{
			name: "Sport shorts and a sports bra",
			get requirements() { return V.boughtItem.clothing.sports === 1; },
			exposure: 1,
		}
	)
	.set("sport shorts",
		{
			name: "Sport shorts",
			get requirements() { return V.boughtItem.clothing.sports === 1; },
			exposure: 2,
			topless: true
		}
	)
	.set("a sports bra",
		{
			name: "Sports bra",
			get requirements() { return V.boughtItem.clothing.sports === 1; },
			exposure: 3
		}
	)
	.set("sport shorts and a t-shirt",
		{
			name: "Sport shorts and a t-shirt",
			get requirements() { return V.boughtItem.clothing.sports === 1 && V.boughtItem.clothing.casual === 1; },
			exposure: 0
		}
	)
	.set("a nice pony outfit",
		{
			name: "Pony outfit (nice)",
			get requirements() { return V.boughtItem.clothing.pony === 1; },
			exposure: 1
		}
	)
	.set("a slutty pony outfit",
		{
			name: "Pony outfit (slutty)",
			get requirements() { return V.boughtItem.clothing.pony === 1; },
			exposure: 2
		}
	)
	.set("a monokini",
		{
			name: "Monokini",
			get requirements() { return V.boughtItem.clothing.swimwear === 1; },
			exposure: 3,
			note: "Boob fetishists enjoy."
		}
	)
	.set("a one-piece swimsuit",
		{
			name: "One-piece swimsuit",
			get requirements() { return V.boughtItem.clothing.swimwear === 1; },
			exposure: 1
		}
	)
	.set("a striped bra",
		{
			name: "Striped bra",
			get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; },
			exposure: 3
		}
	)
	.set("striped panties",
		{
			name: "Striped panties",
			get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; },
			exposure: 2,
			topless: true
		}
	)
	.set("striped underwear",
		{
			name: "Striped underwear",
			get requirements() { return V.boughtItem.clothing.pantsu === 1 || V.continent === "Japan"; },
			exposure: 2,
			topless: true
		}
	)

	// "Normal" things:
	.set("an apron",
		{
			name: "Apron",
			exposure: 2,
			note: "Increases just devotion for submissives, humiliation fetishists and visibly pregnant pregnancy fetishists regardless of devotion level."
		}
	)
	.set("slutty jewelry",
		{
			name: "Bangles",
			exposure: 3,
			fs: {loves: new Set(["FSEgyptianRevivalist"])}
		}
	)
	.set("clubslut netting",
		{
			name: "Clubslut netting",
			exposure: 3,
			fs: {loves: new Set(["FSBodyPurist", "FSIntellectualDependency"])},
		}
	)
	.set("cutoffs and a t-shirt",
		{
			name: "Cutoffs and a t-shirt",
			exposure: 0
		}
	)
	.set("a comfortable bodysuit",
		{
			name: "Bodysuit",
			exposure: 1,
			fs: {loves: new Set(["FSBodyPurist"])},
		}
	)
	.set("a cheerleader outfit",
		{
			name: "Cheerleader",
			exposure: 2,
			fs: {loves: new Set(["FSGenderFundamentalist", "FSYouthPreferentialist"])},
		}
	)
	.set("a fallen nuns habit",
		{
			name: "Fallen nun",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			exposure: 3
		}
	)
	.set("a hijab and abaya",
		{
			name: "Hijab and abaya",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			exposure: 0
		}
	)
	.set("a leotard",
		{
			name: "Leotard",
			exposure: 1,
			fs: {loves: new Set(["FSBodyPurist"])},
		}
	)
	.set("a slutty maid outfit",
		{
			name: "Maid (slutty)",
			exposure: 2,
			fs: {loves: new Set(["FSSlaveProfessionalism", "FSIntellectualDependency"])},
		}
	)
	.set("a mini dress",
		{
			name: "Mini dress",
			exposure: 2
		}
	)
	.set("attractive lingerie",
		{
			name: "Nice lingerie",
			exposure: 2
		}
	)
	.set("a slutty nurse outfit",
		{
			name: "Nurse (slutty)",
			exposure: 2
		}
	)
	.set("overalls",
		{
			name: "Overalls",
			exposure: 1
		}
	)
	.set("panties",
		{
			name: "Panties",
			exposure: 2,
			topless: true
		}
	)
	.set("a scalemail bikini",
		{
			name: "Scalemail bikini",
			exposure: 2
		}
	)
	.set("a schoolgirl outfit",
		{
			name: "Schoolgirl",
			exposure: 1,
			fs: {loves: new Set(["FSGenderFundamentalist", "FSYouthPreferentialist"])},
		}
	)
	.set("a slutty outfit",
		{
			name: "Slutty outfit",
			exposure: 2,
			fs: {loves: new Set(["FSIntellectualDependency"])},
		}
	)
	.set("spats and a tank top",
		{
			name: "Spats and a tank top",
			exposure: 0
		}
	)
	.set("a string bikini",
		{
			name: "String bikini",
			exposure: 3,
			fs: {loves: new Set(["FSBodyPurist", "FSIntellectualDependency"])},
		}
	)
	.set("a succubus outfit",
		{
			name: "Succubus costume",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			exposure: 3
		}
	)
	.set("slutty business attire",
		{
			name: "Suit (slutty)",
			exposure: 2,
			fs: {
				loves: new Set(["FSMaturityPreferentialist", "FSSlaveProfessionalism"])
			},
		}
	)
	.set("a halter top dress",
		{
			name: "Haltertop dress",
			exposure: 0,
			fs: {loves: new Set(["FSBodyPurist", "FSSlaveProfessionalism"])},
		}
	)
	.set("chains",
		{
			name: "Chains",
			fs: {
				unlocks: "FSDegradationist",
				loves: new Set(["FSDegradationist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			get requirements() { return V.boughtItem.clothing.chains === 1; },
			exposure: 4,
			harsh: true,
			note: "Increases devotion and fear for slaves who are disobedient and not terrified. Masochists who are at least ambivalent gain devotion, may also cause masochism."
		}
	)
	.set("no clothing",
		{
			name: "Naked",
			exposure: 4,
			harsh: true,
			fs: {
				loves: new Set(["FSPhysicalIdealist", "FSIntellectualDependency"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
		}
	)
	.set("a penitent nuns habit",
		{
			name: "Penitent nun",
			fs: {
				loves: new Set(["FSChattelReligionist"]),
			},
			exposure: 0,
			harsh: true,
			note: "Increases devotion and fear but damages health, may cause masochism."
		}
	)
	.set("restrictive latex",
		{
			name: "Restrictive latex",
			fs: {loves: new Set(["FSBodyPurist"])},
			exposure: 3,
			harsh: true,
			note: "Increases fear and devotion for resistant slaves and just devotion for obedient, non-terrified submissives."
		}
	)
	.set("shibari ropes",
		{
			name: "Shibari ropes",
			fs: {
				loves: new Set(["FSDegradationist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			exposure: 4,
			harsh: true,
			note: "Increases fear and devotion for resistant slaves and just devotion for obedient, non-terrified submissives."
		}
	)
	.set("uncomfortable straps",
		{
			name: "Uncomfortable straps",
			exposure: 3,
			harsh: true,
			fs: {
				loves: new Set(["FSDegradationist"]),
				tolerates: new Set(["FSChattelReligionist"]),
			},
			note: "Increases devotion and fear for slaves who are disobedient and not terrified. Masochists who are at least ambivalent gain devotion, may also cause masochism."
		}
	);

/**
 * @typedef {object} slaveWear
 * @property {string} name
 * @property {itemFS} [fs]
 * @property {boolean} [requirements]
 * @property {boolean} [harsh]
 * @property {string} [note]
 */

/**
 * @typedef {Map<string, slaveWear>} slaveWearCategory
 */

/** @type {Object.<string, slaveWearCategory>} string should be the slave property being modified.*/
App.Data.slaveWear = {
	collar: new Map([
		["stylish leather", {name: "Stylish leather"}],
		["satin choker", {name: "Satin choker"}],
		["silk ribbon", {name: "Silken ribbon"}],
		["heavy gold", {name: "Heavy gold"}],
		["pretty jewelry", {name: "Pretty jewelry"}],
		["nice retirement counter",
			{
				name: "Nice retirement counter",
				get requirements() {
					return V.seeAge === 1;
				}
			}
		],
		["preg biometrics",
			{
				name: "Pregnancy biometrics",
				get requirements() {
					return V.seePreg === 1;
				},
				note: "Increases devotion for those who have pregnancy fetish while fertile or a humiliation fetish. For others obedient ones gain devotion, ambivalent ones gain fear and devotion and resistant ones lose devotion and gain fear."
			}
		],
		["bell collar",
			{
				name: "Bell",
				note: "On non-obedient slaves reduces fear a lot and devotion somewhat."
			},
		],
		["leather with cowbell",
			{
				name: "Cowbell",
				note: "On obedient slaves with boob fetish increases devotion, on disobedient slaves reduces fear a lot and devotion somewhat."
			}
		],
		["bowtie",
			{
				name: "Bowtie collar",
				fs: {
					unlocks: "FSGenderFundamentalist",
					loves: new Set(["FSGenderFundamentalist"]),
				},
				get requirements() {
					return V.boughtItem.clothing.bunny === 1;
				}
			}
		],
		["neck tie",
			{
				name: "Neck tie",
				fs: {
					unlocks: "FSPaternalist",
					loves: new Set(["FSPaternalist"]),
				},
				get requirements() {
					return V.boughtItem.clothing.conservative === 1;
				}
			}
		],
		["ancient Egyptian",
			{
				name: "Ancient Egyptian",
				fs: {
					unlocks: "FSEgyptianRevivalist",
					loves: new Set(["FSEgyptianRevivalist"]),
				},
				get requirements() {
					return V.boughtItem.clothing.egypt === 1;
				}
			}
		],
		["tight steel",
			{
				name: "Tight steel",
				fs: {
					loves: new Set(["FSChattelReligionist"])
				},
				harsh: true
			}
		],
		["cruel retirement counter",
			{
				name: "Cruel retirement counter",
				fs: {
					loves: new Set(["FSChattelReligionist"])
				},
				get requirements() {
					return V.seeAge === 1;
				},
				harsh: true
			}
		],
		["uncomfortable leather",
			{
				name: "Uncomfortable leather",
				fs: {
					loves: new Set(["FSChattelReligionist"])
				},
				harsh: true
			}
		],
		["shock punishment",
			{
				name: "Shock punishment",
				harsh: true,
				note: "For non-obedient slaves increases fear a great deal and reduces devotion, for resistant non-odd slaves it affects both much more a single time and gives the odd flaw."
			}
		],
		["neck corset",
			{
				name: "Neck corset",
				harsh: true
			}
		],
	]),

	faceAccessory: new Map([
		["porcelain mask",
			{
				name: "Porcelain mask",
				note: "Obscures the face, increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
			}
		],
		["cat ears",
			{
				name: "Cat ears",
				note: "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
			}
		],
	]),

	vaginalAttachment: new Map([
		["none", {name: "None"}],
		["vibrator",
			{
				name: "Vibrating attachment",
				get requirements() {
					return V.boughtItem.toys.vaginalAttachments === 1;
				},
				vibrates: 1
			}
		],
		["smart vibrator",
			{
				name: "Smart vibrating attachment",
				get requirements() {
					return V.boughtItem.toys.smartVaginalAttachments === 1;
				},
				vibrates: 2
			}
		]
	]),

	dickAccessory: new Map([
		["none", {name: "None"}],
		["bullet vibrator", {name: "Bullet vibrator"}],
		["smart bullet vibrator",
			{
				name: "Smart bullet vibrator",
				get requirements() {
					return V.boughtItem.toys.smartVibes === 1;
				}
			}
		]
	]),

	buttplugAttachment: new Map([
		["none", {name: "None"}],
		["tail",
			{
				name: "Tail",
				get requirements() {
					return V.boughtItem.toys.buttPlugTails === 1;
				}
			}
		],
		["fox tail",
			{
				name: "Fox tail",
				get requirements() {
					return V.boughtItem.toys.buttPlugTails === 1;
				}
			}
		],
		["cat tail",
			{
				name: "Cat tail",
				get requirements() {
					return V.boughtItem.toys.buttPlugTails === 1;
				}
			}
		],
		["cow tail",
			{
				name: "Cow tail",
				get requirements() {
					return V.boughtItem.toys.buttPlugTails === 1;
				}
			}
		]
	]),

	armAccessory: new Map([
		// ["none", {name: "None"}],
		["hand gloves", {name: "Hand gloves"}],
		["elbow gloves", {name: "Elbow gloves"}]

	]),

	legAccessory: new Map([
		// ["none", {name: "None"}],
		["short stockings", {name: "Short stockings"}],
		["long stockings", {name: "Long stockings"}]

	]),
};

/**
 * @typedef {object} mouthAccessory
 * @property {string} name
 * @property {boolean} [requirements]
 * @property {string} [note]
 */

/** @type {Map<FC.MouthAccessory, mouthAccessory>} */
App.Data.mouthAccessory = new Map([
	["ball gag",
		{
			name: "Ball gag",
			note: "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
		}
	],
	["bit gag",
		{
			name: "Bit gag",
			note: "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
		}
	],
	["ring gag",
		{
			name: "Ring gag",
			note: "Increases fear and devotion for disobedient slaves, submissives and nymphos also enjoy wearing one."
		}
	],
	["massive dildo gag",
		{
			name: "Massive dildo gag",
			get requirements() {
				return V.boughtItem.toys.gags === 1;
			},
			note: "Increases oral skill up to a point and causes fear for disobedient slaves."
		}
	],
	["dildo gag",
		{
			name: "Dildo gag",
			note: "Increases oral skill up to a point and causes fear for disobedient slaves."
		}
	],
]);

/**
 * @typedef {object} slaveShoes
 * @property {string} name
 * @property {itemFS} [fs]
 * @property {boolean} [requirements]
 * @property {boolean} [harsh]
 * @property {number} heelHeight height in cm. Over 4cm they may totter. 21cm and over (8 inch heels) will be painful/extreme
 * @property {number} platformHeight height in cm. Adds to heel height.
 */

/**
 * @type {Map<FC.WithNone<FC.Shoes>, slaveShoes>} slaveShoesCategory
 */
App.Data.shoes = new Map([ // TODO: add lift property
	["none",
		{
			name: "Barefoot",
			heelHeight: 0,
			platformHeight: 0
		}
	],
	["flats",
		{
			name: "Flats",
			heelHeight: 0,
			platformHeight: 0
		}
	],
	["pumps",
		{
			name: "Pumps",
			heelHeight: 5, // 2 inch heels
			platformHeight: 0
		}
	],
	["heels",
		{
			name: "Heels",
			heelHeight: 13, // 5 inch heels
			platformHeight: 0
		}
	],
	["boots",
		{
			name: "Thigh boots",
			heelHeight: 13, // 5 inch heels
			platformHeight: 0
		}
	],
	["extreme heels",
		{
			name: "Painfully extreme heels",
			heelHeight: 21, // 8 inch heels
			platformHeight: 0
		}
	],
	["platform shoes",
		{
			name: "Platforms",
			fs: {
				unlocks: "FSStatuesqueGlorification",
				loves: new Set(["FSStatuesqueGlorification"])
			},
			get requirements() {
				return (V.boughtItem.shoes.heels === 1);
			},
			heelHeight: 0,
			platformHeight: 8 // 3 inch platform, no heels
		}
	],
	["platform heels",
		{
			name: "Platform heels",
			fs: {
				unlocks: "FSStatuesqueGlorification",
				loves: new Set(["FSStatuesqueGlorification"])
			},
			get requirements() {
				return (V.boughtItem.shoes.heels === 1);
			},
			heelHeight: 13, // 8 inches, but not painful like extremes (3 inch platforms)
			platformHeight: 8
		}
	],
	["extreme platform heels",
		{
			name: "Painfully extreme platform heels",
			fs: {
				unlocks: "FSStatuesqueGlorification",
				loves: new Set(["FSStatuesqueGlorification"])
			},
			get requirements() {
				return (V.boughtItem.shoes.heels === 1);
			},
			heelHeight: 21, // 12 inches! 8 inch heel, 4 inch platform
			platformHeight: 10
		}
	],
]);

/**
 * @typedef {object} slaveButtplugs
 * @property {string} name
 * @property {itemFS} [fs]
 * @property {boolean} [requirements]
 * @property {0|1|2|3} width
 * @property {0|1|2} length
 */

/**
 * @type {Map<string, slaveButtplugs>}
 */
App.Data.buttplug = new Map([
	["none",
		{
			name: "None",
			width: 0,
			length: 0
		}
	],
	["plug",
		{
			name: "Standard plug",
			width: 1,
			length: 1
		}
	],
	["long plug",
		{
			name: "Long plug",
			get requirements() {
				return V.boughtItem.toys.buttPlugs === 1;
			},
			width: 1,
			length: 2
		}
	],
	["large plug",
		{
			name: "Large plug",
			width: 2,
			length: 1
		}
	],
	["long, large plug",
		{
			name: "Long, large plug",
			get requirements() {
				return V.boughtItem.toys.buttPlugs === 1;
			},
			width: 2,
			length: 2
		}
	],
	["huge plug",
		{
			name: "Huge plug",
			width: 3,
			length: 1
		}
	],
	["long, huge plug",
		{
			name: "Long, huge plug",
			get requirements() {
				return V.boughtItem.toys.buttPlugs === 1;
			},
			width: 3,
			length: 2
		}
	]
]);
/**
 * @typedef {object} vaginalAccessories
 * @property {string} name
 * @property {itemFS} [fs]
 * @property {boolean} [requirements]
 * @property {0|1|2|3} width
 * @property {0|1|2} length
 * @property {0|1|2} [vibrates=0] 0: none, 1: standard, 2: "smart" vibe
 */

/**
 * @type {Map<string, vaginalAccessories>}
 */
App.Data.vaginalAccessory = new Map([
	["none",
		{
			name: "None",
			width: 0,
			length: 0
		}
	],
	["bullet vibrator",
		{
			name: "Bullet vibrator",
			width: 0,
			length: 1,
			vibrates: 1
		}
	],
	["smart bullet vibrator",
		{
			name: "Smart bullet vibrator",
			get requirements() {
				return V.boughtItem.toys.smartVibes === 1;
			},
			width: 0,
			length: 1,
			vibrates: 2
		}
	],
	["dildo",
		{
			name: "Dildo",
			width: 1,
			length: 1
		}
	],
	["long dildo",
		{
			name: "Long dildo",
			get requirements() {
				return V.boughtItem.toys.dildos === 1;
			},
			width: 1,
			length: 2
		}
	],
	["large dildo",
		{
			name: "Large dildo",
			width: 2,
			length: 1
		}
	],
	["long, large dildo",
		{
			name: "Long, large dildo",
			get requirements() {
				return V.boughtItem.toys.dildos === 1;
			},
			width: 2,
			length: 2
		}
	],
	["huge dildo",
		{
			name: "Huge dildo",
			get requirements() {
				return V.boughtItem.toys.dildos === 1;
			},
			width: 3,
			length: 1
		}
	],
	["long, huge dildo",
		{
			name: "Long, huge dildo",
			get requirements() {
				return V.boughtItem.toys.dildos === 1;
			},
			width: 3,
			length: 2
		}
	]
]);

/**
 * @typedef {slaveWear} bellyAccessory
 * @property {1|2|3|4} [empathyBelly]
 */
/** @type {Map<FC.BellyAccessory, bellyAccessory>} */
App.Data.bellyAccessory = new Map([
	["none", {name: "None"}],
	["a corset",
		{
			name: "Tight corset",
			note: "Slowly narrows the waist into a wispy one."
		}
	],
	["an extreme corset",
		{
			name: "Extreme corset",
			note: "Narrows the waist up to an absurd level, painfully if waist is feminine or wider (increasing obedience and fear in resistant slaves), but risks miscarriage if a pregnant belly becomes too big."
		}
	],
	["a support band",
		{
			name: "Supportive band",
			note: "Eases the pains of pregnancy and reduces chance of miscarriage."
		}
	],
	["a small empathy belly",
		{
			name: "1st Trimester belly",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"])
			},
			get requirements() {
				return V.boughtItem.clothing.belly === 1;
			},
			empathyBelly: 1
		}
	],
	["a medium empathy belly",
		{
			name: "2nd Trimester belly",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"])
			},
			get requirements() {
				return V.boughtItem.clothing.belly === 1;
			},
			empathyBelly: 2
		}
	],
	["a large empathy belly",
		{
			name: "3rd Trimester belly",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"])
			},
			get requirements() {
				return V.boughtItem.clothing.belly === 1;
			},
			empathyBelly: 3
		}
	],
	["a huge empathy belly",
		{
			name: "3rd Trimester twins belly",
			fs: {
				unlocks: "FSRepopulationFocus",
				loves: new Set(["FSRepopulationFocus"])
			},
			get requirements() {
				return V.boughtItem.clothing.belly === 1;
			},
			empathyBelly: 4
		}
	]
]);
/**
 * @typedef {object} slaveWearChastity
 * @property {string} name
 * @property {object} updateSlave
 * @property {string} [note]
 * @property {itemFS} [fs]
 */

/** @type {Map<string, slaveWearChastity>} */
App.Data.chastity = new Map([
	// '.value' must be a string, so using update slave so I can update multiple values.
	["none",
		{
			name: "None",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 0,
				chastityPenis: 0,
				chastityVagina: 0
			},
		}
	],
	["anal chastity",
		{
			name: "Anal chastity",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 1,
				chastityPenis: 0,
				chastityVagina: 0
			},
			note: "Prevents losing anal virginity."
		}
	],
	["chastity belt",
		{
			name: "Chastity belt",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 0,
				chastityPenis: 0,
				chastityVagina: 1
			},
			note: "Prevents losing virginity, has various effects, obedient virgins, buttsluts and ones with relatively high sex drive are most affected."
		}
	],
	["combined chastity belt",
		{
			name: "Combined chastity belt",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 1,
				chastityPenis: 0,
				chastityVagina: 1
			},
			note: "Prevents losing virginities, has various effects, obedient virgins, buttsluts and ones with relatively high sex drive are most affected."
		}
	],
	["chastity cage",
		{
			name: "Chastity cage",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 0,
				chastityPenis: 1,
				chastityVagina: 0
			},
			note: "Prevents using penis, has various effects, devotion, trust and sex drive of unresistant slaves with healthy sex drive all suffer from wearing one unless they're a masochist, nympho, neglectful, buttslut, sterile or lack balls."
		}
	],
	["combined chastity cage",
		{
			name: "Combined chastity cage",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 1,
				chastityPenis: 1,
				chastityVagina: 0
			},
			note: "Protects both penis and anus from sex, has various effects, devotion and trust and sex drive of unresistant slaves with healthy sex drive all suffer from wearing one unless they're a masochist, nympho, neglectful, buttslut, sterile or lack balls."
		}
	],
	["genital chastity",
		{
			name: "Genital chastity",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 0,
				chastityPenis: 1,
				chastityVagina: 1
			},
			note: "Protects both penis and vagina from sex, has various effects."
		}
	],
	["full chastity",
		{
			name: "Full chastity",
			updateSlave: {
				choosesOwnChastity: 0,
				chastityAnus: 1,
				chastityPenis: 1,
				chastityVagina: 1
			},
			note: "Protects penis, vagina and anus, has various effects."
		}
	],
	["choose own chastity",
		{
			name: "Choose own chastity",
			fs: {unlocks: "FSRestart"},
			updateSlave: {
				choosesOwnChastity: 1
			},
		}
	],
	["revoke choosing own chastity",
		{
			name: "Revoke choosing own chastity",
			fs: {unlocks: "FSRestart"},
			updateSlave: {
				choosesOwnChastity: 0
			},
		}
	]
]);


code:
App.Data.clothes.set("a slave gown",
	{
		name: "Slave gown",
		exposure: 0,
		fs: {loves: new Set(["FSBodyPurist"])},
		desc: {
			summary: function(slave) {
				const r = [];
				const {He, he, his} = getPronouns(slave);
				const bothFeet = hasBothLegs(slave);
				const feet = bothFeet ? "feet" : "foot";

				r.push(`a gorgeous affair`);
				if (isAmputee(slave)) {
					r.push(`tailored to favor ${his} lack of arms and legs.`);
				} else if (!hasAnyLegs(slave)) {
					r.push(`with cuts that offer tantalizing glimpses of delicate flesh.`);
				} else {
					r.push(`with cuts that offer tantalizing glimpses of delicate flesh.`);
					r.push(`${He} completes the look with`);
					switch (slave.shoes) {
						case "flats":
							if (bothFeet) {
								r.push(`a pair of fashionable slingback sandals.`);
							} else {
								r.push(`a fashionable slingback sandal.`);
							}
							break;
						case "boots":
							if (bothFeet) {
								r.push(`elegant worked leather boots.`);
							} else {
								r.push(`an elegant worked leather boot.`);
							}
							break;
						case "heels":
							if (bothFeet) {
								r.push(`kitten heels.`);
							} else {
								r.push(`a kitten heel.`);
							}
							break;
						case "pumps":
							if (bothFeet) {
								r.push(`sleek pumps.`);
							} else {
								r.push(`a sleek heel.`);
							}
							break;
						case "extreme heels":
							if (bothFeet) {
								r.push(`daring spike heels so high ${his} butt is at dick height.`);
							} else {
								r.push(`a daring spike heel so high ${he} can't even stand.`);
							}
							break;
						case "platform shoes":
							if (bothFeet) {
								r.push(`stylish platform shoes.`);
							} else {
								r.push(`a stylish platform shoe.`);
							}
							break;
						case "platform heels":
							if (bothFeet) {
								r.push(`elegant platform heels.`);
							} else {
								r.push(`an elegant platform heel.`);
							}
							break;
						case "extreme platform heels":
							if (bothFeet) {
								r.push(`elegant platform heels so high ${his} butt is at dick height.`);
							} else {
								r.push(`an elegant platform heel so high ${he} can't stand even with assistance.`);
							}
							break;
						default:
							r.push(`nothing on ${his} bare ${feet}.`);
					}
				}
				return r.join(" ");
			},
			upperFace: function(slave) {
				return `nice frameless glasses,`;
			},
			hStyle: function(slave) {
				const r = [];
				const {
					he, his
				} = getPronouns(slave);

				if (slave.fuckdoll === 0) {
					switch (slave.hStyle) {
						case "neat":
							if (slave.hLength > 100) {
								r.push(`cascades gorgeously down ${his} bare back.`);
							} else if (slave.hLength > 30) {
								r.push(`flows fashionably down ${his} bare back.`);
							} else if (slave.hLength > 10) {
								r.push(`follows the latest fashion.`);
							} else {
								r.push(`is gelled into a fashionable wave.`);
							}
							break;
						case "up":
							if (slave.hLength > 100) {
								r.push(`is piled up on ${his} head in a perfect 60's beehive.`);
							} else if (slave.hLength > 30) {
								r.push(`is piled up on ${his} head in a perfect 60's beehive.`);
							} else if (slave.hLength > 10) {
								r.push(`is piled up on ${his} head in a perfect 60's 'do.`);
							} else {
								r.push(`is combed back.`);
							}
							break;
						case "tails":
							if (slave.hLength > 100) {
								r.push(`is combed into beautiful long tails, one of which comes around to run down ${his} chest.`);
							} else if (slave.hLength > 30) {
								r.push(`is combed into beautiful tails, one of which comes around to fall between ${his} breasts.`);
							} else if (slave.hLength > 10) {
								r.push(`is combed into short tails set low at the nape of ${his} neck.`);
							} else {
								r.push(`is too short to be kept in proper tails, so it's simply combed back.`);
							}
							break;
						case "ponytail":
							if (slave.hLength > 100) {
								r.push(`is combed into a beautiful long ponytail, which swooshes as ${he} moves.`);
							} else if (slave.hLength > 30) {
								r.push(`is combed into a beautiful ponytail, which swooshes as ${he} moves.`);
							} else if (slave.hLength > 10) {
								r.push(`is combed into a short ponytail set low at the nape of ${his} neck.`);
							} else {
								r.push(`is too short to be kept in a proper ponytail, so it's simply combed back.`);
							}
							break;
						case "braided":
							if (slave.hLength > 100) {
								r.push(`is combed into beautiful long braids, one of which comes around to run down ${his} chest.`);
							} else if (slave.hLength > 30) {
								r.push(`is in beautiful braids, one of which comes around to fall between ${his} breasts.`);
							} else if (slave.hLength > 10) {
								r.push(`is combed into short braids set low at the nape of ${his} neck.`);
							} else {
								r.push(`is too short to be kept in proper braids, so it's simply combed back.`);
							}
							break;
						case "dreadlocks":
							if (slave.hLength > 100) {
								r.push(`is in dreadlocks, spreading out in many directions and almost reaching the ground.`);
							} else if (slave.hLength > 30) {
								r.push(`is in dreadlocks, spreading out in many directions.`);
							} else if (slave.hLength > 10) {
								r.push(`is in short dreadlocks, spreading around ${his} head.`);
							} else {
								r.push(`is too short to be kept in proper dreadlocks, so it's simply combed back.`);
							}
							break;
						case "curled":
							if (slave.hLength > 100) {
								r.push(`is curled into long flowing locks, almost reaching the ground.`);
							} else if (slave.hLength > 30) {
								r.push(`is curled into long locks, reaching past ${his} shoulders.`);
							} else if (slave.hLength > 10) {
								r.push(`is curled into short locks.`);
							} else {
								r.push(`is in short curls.`);
							}
							break;
						case "permed":
							if (slave.hLength > 100) {
								r.push(`is permed into long flowing curls, almost reaching the ground.`);
							} else if (slave.hLength > 30) {
								r.push(`is permed, reaching past ${his} shoulders.`);
							} else if (slave.hLength > 10) {
								r.push(`is permed into short waves.`);
							} else {
								r.push(`is permed into short curls.`);
							}
							break;
						case "luxurious":
							if (slave.hLength > 100) {
								r.push(`is in luxurious layered locks flowing gorgeously down ${his} bare back.`);
							} else if (slave.hLength > 30) {
								r.push(`is in luxurious layered locks flowing gorgeously down ${his} bare back.`);
							} else if (slave.hLength > 10) {
								r.push(`is in luxuriously styled short locks.`);
							} else {
								r.push(`is in luxuriously styled short locks.`);
							}
							break;
						case "strip":
							if (slave.hLength > 100) {
								r.push(`is shaved into a strip atop ${his} head that cascades magnificently down ${his} back.`);
							} else if (slave.hLength > 30) {
								r.push(`is shaved into a long braided strip.`);
							} else if (slave.hLength > 10) {
								r.push(`is shaved into a strip.`);
							} else {
								r.push(`is shaved into a mohawk.`);
							}
							break;
						case "undercut":
							if (slave.hLength > 100) {
								r.push(`is shaved on one side into a long undercut that falls well past ${his} breasts.`);
							} else if (slave.hLength > 30) {
								r.push(`is shaved to one side, the other half falling down to ${his} neck.`);
							} else if (slave.hLength > 10) {
								r.push(`is shaved to one side, the other half falling just over one eye.`);
							} else {
								r.push(`is shaved to one side in a pixie-like undercut.`);
							}
							break;
						case "bangs":
							if (slave.hLength > 100) {
								r.push(`is cut straight across ${his} face, hiding ${his} eyes.`);
							} else if (slave.hLength > 30) {
								r.push(`is cut straight across ${his} face, partially hiding ${his} eyes.`);
							} else if (slave.hLength > 10) {
								r.push(`is cut straight above ${his} eyebrows.`);
							} else {
								r.push(`is cut straight across ${his} forehead.`);
							}
							break;
						case "hime":
							if (slave.hLength > 100) {
								r.push(`cascades down ${his} bare back in a hime cut with shoulder-length side-locks.`);
							} else if (slave.hLength > 30) {
								r.push(`flows down ${his} bare back in a hime cut with cheek-length side-locks.`);
							} else if (slave.hLength > 10) {
								r.push(`is styled into a hime cut with cheek-length side-locks.`);
							} else {
								r.push(`is styled into a hime cut with cheek-length side-locks.`);
							}
							break;
						case "drills":
							if (slave.hLength > 100) {
								r.push(`is wound into enormous, exquisite coils that come to rest across ${his} chest.`);
							} else if (slave.hLength > 30) {
								r.push(`is wound into large coils which rest atop ${his} breasts.`);
							} else if (slave.hLength > 10) {
								r.push(`is in a pair of short coils.`);
							} else {
								r.push(`is too short to be kept in proper tails, so it's simply combed back.`);
							}
							break;
						case "crown braid":
							if (slave.hLength >= 100) {
								r.push(`is partly braided into a grand-looking crown braid that circles ${his} head, while the rest of it flows down to ${his} calves.`);
							} else if (slave.hLength >= 30) {
								r.push(`is partly braided into a elegant-looking crown braid that circles ${his} head, while the rest of it flows down to ${his} shoulders.`);
							} else if (slave.hLength >= 10) {
								r.push(`is braided into a small crown braid that circles ${his} head.`);
							} else {
								r.push(`is too short to be kept in a crown braid so it's simply combed back.`);
							}
							break;
						case "dutch braid":
							if (slave.hLength >= 100) {
								r.push(`is braided into a single dutch braid that reaches down to ${his} calves.`);
							} else if (slave.hLength >= 30) {
								r.push(`is braided into a single dutch braid that reaches down to below ${his} shoulders.`);
							} else if (slave.hLength >= 10) {
								r.push(`is braided into a single dutch braid that reaches down to just below ${his} neck.`);
							} else {
								r.push(`is too short to be kept in a dutch braid so it's simply combed back.`);
							}
							break;
						case "double dutch braid":
							if (slave.hLength >= 100) {
								r.push(`is braided into two dutch braids that reach down to ${his} calves.`);
							} else if (slave.hLength >= 30) {
								r.push(`is braided into two dutch braids that reach down to below ${his} shoulders.`);
							} else if (slave.hLength >= 10) {
								r.push(`is braided into two dutch braids that reach down to just below ${his} neck.`);
							} else {
								r.push(`is too short to be kept in dutch braids so it's simply combed back.`);
							}
							break;
						case "bald":
							r.push(`is completely bald.`);
					}
				}
				return r.join(" ");
			},
			earPiercing: function(slave) {
				const {He} = getPronouns(slave);
				return `${He}'s wearing lovely diamond earrings; the stones are cut in an alluring, feminine style.`;
			},
			corsetPiercing: function(slave) {
				const {his} = getPronouns(slave);
				return `they're revealed by the swooping back of ${his} gown and laced up with matching silk ribbon.`;
			},
			clothingCorset: function(slave) {
				const r =[];
				const {His, his} = getPronouns(slave);
				if (slave.bellyAccessory === "a corset") {
					r.push(`${His} gown has an elegant integral corset.`);
				} else if (slave.bellyAccessory === "an extreme corset") {
					r.push(`${His} gown has extreme corsetage built into it.`);
				} else if (slave.bellyAccessory === "a support band") {
					r.push(`${His} support band is concealed by ${his} gown.`);
				}
				return r.join(" ");
			},
			boobs: function(slave) {
				const r = [];
				const {his} = getPronouns(slave);
				const noun = App.Desc.boobBits.noun(slave.boobs, false, false);
				const adjNoun = App.Desc.boobBits.noun(slave.boobs, false, true);
				r.push(`${slave.slaveName}'s slave gown`);
				if (slave.boobs > 12000) {
					r.push(`is no longer able to cover ${his} ${adjNoun}. Instead, it has been redesigned to draw the eye to them.`);
				} else if (slave.boobs > 4000) {
					r.push(`is carefully engineered and is somehow able to cover the enormous mass of ${his} breasts.`);
				} else if (slave.boobs > 800) {
					r.push(`is carefully tailored, tastefully covering yet enhancing ${his} ${adjNoun}.`);
				} else if (slave.boobs < 300) {
					r.push(`is carefully tailored to closely hug ${his} flat chest.`);
				} else {
					r.push(`subtly accentuates ${his} ${noun}.`);
				}
				return r.join(" ");
			},
			belly: function(slave) {
				const r = [];
				const {his, him} = getPronouns(slave);
				const isBellyFluidLargest = (slave.bellyFluid >= slave.bellyPreg && slave.bellyFluid >= slave.bellyImplant);

				if (slave.belly >= 1000000) {
					if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material. When not worn, it looks more like a circus tent than something meant to be worn by a human being. On the slave, it gives ${him} a sensual, motherly look as it caresses ${his} unfathomable, hyper-swollen, ${slave.inflationType}-filled belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material, and gives ${him} a sensual, motherly look as it caresses ${his} unfathomable, hyper-swollen, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material, and gives ${him} a sensual, motherly look as it caresses and supports ${his} unfathomable, hyper-swollen pregnant belly. Despite it's size, it still has enough give to allow ${his} unborn children to bulge and squirm as desired.`);
					}
				} else if (slave.belly >= 750000) {
					if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material. When not worn, it looks more like a couch cover than something meant to be worn by a human being. On ${him}, it gives ${him} a sensual, motherly look as it carefully caresses ${his} monolithic, ${slave.inflationType}-filled belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material, and gives ${him} a sensual, motherly look as it carefully caresses ${his} monolithic, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored using a huge quantity of material, and gives ${him} a sensual, motherly look as it carefully caresses and supports ${his} monolithic pregnant belly. It has enough give to allow ${his} unborn children to bulge and squirm as desired.`);
					}
				} else if (slave.belly >= 600000) {
					if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} titanic, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses and supports ${his} titanic bulging pregnant belly.`);
					}
				} else if (slave.belly >= 450000) {
					if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} gigantic, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses and supports ${his} gigantic pregnant belly.`);
					}
				} else if (slave.belly >= 300000) {
					if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} massive, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses and supports ${his} massive pregnant belly.`);
					}
				} else if (slave.belly >= 120000) {
					if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} giant, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses and supports ${his} giant pregnant belly.`);
					}
				} else if (slave.weight > 190) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve and fold of ${his} massively fat belly. Every motion in ${his} impressive gut is elegantly embraced by ${his} gown.`);
				} else if (slave.belly >= 15000 || (slave.bellyAccessory === "a huge empathy belly")) {
					if (slave.bellyAccessory === "a huge empathy belly") {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} huge pregnant belly.`);
					} else if (isBellyFluidLargest) {
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} huge, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} huge pregnant belly.`);
					}
				} else if (slave.belly >= 10000 || (slave.bellyAccessory === "a huge empathy belly") || (slave.bellyAccessory === "a large empathy belly")) {
					if (slave.bellyAccessory === "a large empathy belly") {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} big pregnant belly.`);
					} else if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, almost motherly look, as it carefully caresses ${his} hugely swollen belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} big, implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} big pregnant belly.`);
					}
				} else if (slave.weight > 160) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve and fold of ${his} hugely fat belly.`);
				} else if (slave.weight > 130) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve and fold of ${his} big fat belly.`);
				} else if (slave.belly >= 5000 || (slave.bellyAccessory === "a medium empathy belly")) {
					if (slave.bellyAccessory === "a medium empathy belly") {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} pregnant belly.`);
					} else if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} jiggling ${slave.inflationType}-filled belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} implant-filled belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} pregnant belly.`);
					}
				} else if (slave.weight > 95) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve of ${his} fat belly.`);
				} else if (slave.belly >= 1500 || slave.bellyAccessory === "a small empathy belly") {
					if (slave.bellyAccessory === "a small empathy belly") {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual, motherly look as it carefully caresses ${his} small belly.`);
					} else if (isBellyFluidLargest) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual look as it carefully caresses ${his} ${slave.inflationType}-swollen belly.`);
					} else if (slave.bellyImplant > 0) {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual look as it carefully caresses ${his} implant-rounded belly.`);
					} else {
						r.push(`${slave.slaveName}'s slave gown is carefully tailored, giving ${him} a sensual look as it carefully caresses ${his} growing belly.`);
					}
				} else if (slave.weight > 30) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging every curve of ${his} chubby belly.`);
				} else if (slave.bellyPreg >= 100 || slave.bellyImplant >= 100) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging even the slight bulge to ${his} lower belly.`);
				} else if (slave.muscles > 30) {
					r.push(`${slave.slaveName}'s slave gown is carefully tailored, accentuating and hugging ${his} ripped abs.`);
				}
				return r.join(" ");
			},
			crotch: function(slave) {
				const r = [];
				const {his} = getPronouns(slave);
				r.push(`${slave.slaveName}'s`);
				if (slave.dick > 6) {
					r.push(`lovely gown cannot hide the fact that something massive is lurking`);
					if (hasBothLegs(slave)) {
						r.push(`between ${his} legs.`);
					} else {
						r.push(`underneath it.`);
					}
				} else if (slave.dick > 3) {
					r.push(`cock tents the front of ${his} lovely gown.`);
				} else if (slave.dick > 0 && slave.vagina > -1) {
					r.push(`hermaphroditic genitalia are hidden by ${his} lovely gown.`);
				} else if (slave.dick > 0) {
					r.push(`cock is hidden by ${his} lovely gown.`);
				} else if (slave.vagina === -1) {
					r.push(`featureless groin is concealed by ${his} lovely gown.`);
				} else {
					r.push(`pussy is concealed by ${his} lovely gown.`);
				}
				return r.join(" ");
			},
			butt: function(slave) {
				const r = [];
				const {His, his} = getPronouns(slave);
				r.push(`${His} slave gown`);
				if (slave.butt > 10) {
					r.push(`is tailored as tastefully as possible for ${his} inhuman`);
				} else if (slave.butt > 6) {
					r.push(`is tailored as tastefully as possible for ${his} massive`);
				} else if (slave.butt > 3) {
					r.push(`is tailored to flatter ${his} big`);
				} else {
					r.push(`tastefully clings to ${his}`);
				}
				r.push(`buttocks.`);
				return r.join(" ");
			},
			buttplug: function(slave) {
				const r = [];
				const {His, his} = getPronouns(slave);
				if (slave.chastityAnus) {
					r.push(`${His} pretty gown hides ${his} anal chastity accessory underneath.`);
				} else {
					r.push(`Though ${his} gown is very pretty, ${his} asshole is bare beneath it.`);
				}
				return r.join(" ");
			},
		}
	}
);

repo_name: Fekenol/fc

license: mit


code:
/**
 * @type {FC.Rules.LivingFreezed}
 * @enum {string}
 */
globalThis.LivingRule = Object.freeze({LUXURIOUS: 'luxurious', NORMAL: 'normal', SPARE: 'spare'});
/**
 * @type {FC.Rules.RestFreezed}
 * @enum {string}
 */
globalThis.RestRule = Object.freeze({
	MANDATORY: 'mandatory', MAX: 'permissive', MID: 'restrictive', MIN: 'cruel', NONE: 'none'
});
/**
 * @type {FC.AssignmentFreeze}
 * @enum {string}
 */
globalThis.Job = Object.freeze({
	// Penthouse Assignments
	REST: 'rest',
	FUCKTOY: 'please you',
	CLASSES: 'take classes',
	HOUSE: 'be a servant',
	WHORE: 'whore',
	PUBLIC: 'serve the public',
	SUBORDINATE: 'be a subordinate slave',
	MILKED: 'get milked',
	GLORYHOLE: 'work a glory hole',
	CONFINEMENT: 'stay confined',
	// Leadership Assignments
	BODYGUARD: 'guard you',
	HEADGIRL: 'be your Head Girl',
	HEADGIRLSUITE: 'live with your Head Girl',
	RECRUITER: 'recruit girls',
	AGENT: 'be your agent',
	AGENTPARTNER: 'live with your agent',
	// Facility Assignments
	ARCADE: 'be confined in the arcade',
	MADAM: 'be the Madam',
	BROTHEL: 'work in the brothel',
	WARDEN: 'be the Wardeness',
	CELLBLOCK: 'be confined in the cellblock',
	DJ: 'be the DJ',
	CLUB: 'serve in the club',
	NURSE: 'be the Nurse',
	CLINIC: 'get treatment in the clinic',
	MILKMAID: 'be the Milkmaid',
	DAIRY: 'work in the dairy',
	FARMER: 'be the Farmer',
	FARMYARD: 'work as a farmhand',
	CONCUBINE: 'be your Concubine',
	MASTERSUITE: 'serve in the master suite',
	MATRON: 'be the Matron',
	NURSERY: 'work as a nanny',
	TEACHER: 'be the Schoolteacher',
	SCHOOL: 'learn in the schoolroom',
	STEWARD: 'be the Stewardess',
	QUARTER: 'work as a servant',
	ATTENDANT: 'be the Attendant',
	SPA: 'rest in the spa',
	// Does this one exist?
	BABY_FACTORY: 'labor in the production line',
	// Other
	CHOICE: 'choose her own job',
	// Pseudo-jobs
	LURCHER: '@Lurcher',
	PIT: '@Pit',
	IMPORTED: '@be imported',
	TANK: '@lay in tank'
});

/**
 * @enum {string}
 */
globalThis.PersonalAttention = Object.freeze({
	TRADE: 'trading',
	WAR: 'warfare',
	SLAVING: 'slaving',
	ENGINEERING: 'engineering',
	MEDICINE: 'medicine',
	MAID: 'upkeep',
	HACKING: 'hacking',
	SUPPORTHG: 'HG',
	WHORING: 'whoring',
	BUSINESS: 'business',
	SMUGGLING: 'smuggling',
	SURVEY: 'defensive survey',
	DEVELOPMENT: 'development project',
	TECH: 'technical accidents',
	SEX: 'sex',
	PROCLAMATION: 'proclamation',
	TRAINING: 'slave training',
});

/**
 * @enum {string}
 */
globalThis.DescType = Object.freeze({
	NORMAL: "normal",
	MARKET: "market",
	EVENT: "event",
	SURGERY: "surgery"
});

/**
 * @type {FC.FetishFreeze}
 * @enum {string}
 */
globalThis.Fetish = Object.freeze({
	NONE: "none",
	MINDBROKEN: "mindbroken",
	SUBMISSIVE: "submissive",
	CUMSLUT: "cumslut",
	HUMILIATION: "humiliation",
	BUTTSLUT: "buttslut",
	BOOBS: "boobs",
	SADIST: "sadist",
	MASOCHIST: "masochist",
	DOM: "dom",
	PREGNANCY: "pregnancy",
	BESTIALITY: "bestiality",
});


code:
App.Data.dictionary = {
	"cat": {
		Japanese: "neko"
	},
	"dog": {
		Japanese: "inu"
	},
	"fox": {
		Japanese: "kit"
	},
	"cow": {
		Japanese: "ushi"
	},
	"raccoon": {
		Japanese: "tanuki"
	},
	"rabbit": {
		Japanese: "usagi"
	},
	"squirrel": {
		Japanese: "risu"
	},
	"horse": {
		Japanese: "uma"
	},
};


code:
App.Data.FutureSociety = {
	/**
	 * Each future society contains a record here, along with a noun and adjective form for use in printed text, and the decoration string (normally also an adjective form).
	 * Most of the automatic mechanics for FS adoption, influence, facility decoration, etc, are handled directly from this data; flavor text is not.
	 * @type {Record<FC.FutureSociety, {noun: FC.FutureSocietyNoun, adj: FC.FutureSocietyAdj, deco: FC.FutureSocietyDeco, NPCOnly?: boolean, language?: string, nationality?: string}>} */
	records: ({
		FSSupremacist: {noun: "Racial Supremacism", adj: "Supremacist", deco: "Supremacist"},
		FSSubjugationist: {noun: "Racial Subjugationism", adj: "Subjugationist", deco: "Subjugationist"},
		FSGenderRadicalist: {noun: "Gender Radicalism", adj: "Gender Radicalist", deco: "Gender Radicalist"},
		FSGenderFundamentalist: {noun: "Gender Fundamentalism", adj: "Gender Fundamentalist", deco: "Gender Fundamentalist"},
		FSDegradationist: {noun: "Degradationism", adj: "Degradationist", deco: "Degradationist"},
		FSPaternalist: {noun: "Paternalism", adj: "Paternalist", deco: "Paternalist"},
		FSBodyPurist: {noun: "Body Purism", adj: "Body Purist", deco: "Body Purist"},
		FSTransformationFetishist: {noun: "Transformation Fetishism", adj: "Transformation Fetishist", deco: "Transformation Fetishist"},
		FSYouthPreferentialist: {noun: "Youth Preferentialism", adj: "Youth Preferentialist", deco: "Youth Preferentialist"},
		FSMaturityPreferentialist: {noun: "Maturity Preferentialism", adj: "Maturity Preferentialist", deco: "Maturity Preferentialist"},
		FSSlimnessEnthusiast: {noun: "Slimness Enthusiasm", adj: "Slimness Enthusiast", deco: "Slimness Enthusiast"},
		FSAssetExpansionist: {noun: "Asset Expansionism", adj: "Asset Expansionist", deco: "Asset Expansionist"},
		FSPastoralist: {noun: "Pastoralism", adj: "Pastoralist", deco: "Pastoralist"},
		FSCummunism: {noun: "Cummunism", adj: "Cummunist", deco: undefined, NPCOnly: true},
		FSPhysicalIdealist: {noun: "Physical Idealism", adj: "Physical Idealist", deco: "Physical Idealist"},
		FSHedonisticDecadence: {noun: "Decadent Hedonism", adj: "Decadent Hedonist", deco: "Hedonistic"},
		FSChattelReligionist: {noun: "Chattel Religionism", adj: "Chattel Religionist", deco: "Chattel Religionist"},
		FSNull: {noun: "Multiculturalism", adj: "Multiculturalist", deco: undefined},
		FSIncestFetishist: {noun: "Incest Fetishism", adj: "Incest Fetishist", deco: undefined, NPCOnly: true},
		FSRomanRevivalist: {
			noun:			"Roman Revivalism",
			adj:			"Roman Revivalist",
			deco:			"Roman Revivalist",
			nationality:	"Roman Revivalist",
			language:		"Latin",
		},
		FSNeoImperialist: {
			noun:			"Neo-Imperialism",
			adj:			"Neo-Imperialist",
			deco:			"Neo-Imperialist",
		},
		FSEgyptianRevivalist: {
			noun:			"Egyptian Revivalism",
			adj:			"Egyptian Revivalist",
			deco:			"Egyptian Revivalist",
			nationality:	"Ancient Egyptian Revivalist",
			language:		"Ancient Egyptian",
		},
		FSEdoRevivalist: {
			noun:			"Edo Revivalism",
			adj:			"Edo Revivalist",
			deco:			"Edo Revivalist",
			nationality:	"Edo Revivalist",
			language:		"Japanese",
		},
		FSArabianRevivalist: {
			noun:			"Arabian Revivalism",
			adj:			"Arabian Revivalist",
			deco:			"Arabian Revivalist",
			nationality:	"Arabian Revivalist",
			language:		"Arabic",
		},
		FSChineseRevivalist: {
			noun:			"Chinese Revivalism",
			adj:			"Chinese Revivalist",
			deco:			"Chinese Revivalist",
			nationality:	"Ancient Chinese Revivalist",
			language:		"Chinese",
		},
		FSAztecRevivalist: {
			noun:			"Aztec Revivalism",
			adj:			"Aztec Revivalist",
			deco:			"Aztec Revivalist",
			nationality:	"Aztec Revivalist",
			language:		"Nahuatl",
		},
		FSRepopulationFocus: {noun: "Repopulation Focus", adj: "Repopulationist", deco: "Repopulationist"},
		FSRestart: {noun: "Eugenics", adj: "Eugenics", deco: "Eugenics"},
		FSIntellectualDependency: {noun: "Intellectual Dependency", adj: "Intellectual Dependency", deco: "Intellectual Dependency"},
		FSSlaveProfessionalism: {noun: "Slave Professionalism", adj: "Slave Professional", deco: "Slave Professionalism"},
		FSPetiteAdmiration: {noun: "Petite Admiration", adj: "Petite Admiration", deco: "Petite Admiration"},
		FSStatuesqueGlorification: {noun: "Statuesque Glorification", adj: "Statuesque Glorification", deco: "Statuesque Glorification"}
	}),

	/** Each subarray in this array contains a set of Future Societies which are to be considered mutually exclusive.
	 * They cannot be adopted at the same time by the same arcology, and if adopted by different arcologies,
	 * will automatically conflict and reduce diplomatic relations. */
	mutexGroups: (/** @returns {FC.FutureSociety[][]} */ function() {
		/* this tiny-but-hideous IIFE is the only way I can get typechecking to work properly here, without a JSDoc equivalent to TS "as const" to prevent literal type widening */
		return [
			["FSSupremacist"],
			["FSSubjugationist"],
			["FSGenderRadicalist", "FSGenderFundamentalist"],
			["FSDegradationist", "FSPaternalist"],
			["FSBodyPurist", "FSTransformationFetishist"],
			["FSYouthPreferentialist", "FSMaturityPreferentialist"],
			["FSSlimnessEnthusiast", "FSAssetExpansionist"],
			["FSPastoralist", "FSCummunism"],
			["FSPhysicalIdealist", "FSHedonisticDecadence"],
			["FSChattelReligionist", "FSNull"],
			["FSIncestFetishist"],
			["FSRomanRevivalist", "FSNeoImperialist", "FSEgyptianRevivalist", "FSEdoRevivalist", "FSArabianRevivalist", "FSChineseRevivalist", "FSAztecRevivalist"],
			["FSRepopulationFocus", "FSRestart"],
			["FSIntellectualDependency", "FSSlaveProfessionalism"],
			["FSPetiteAdmiration", "FSStatuesqueGlorification"]
		];
	})(),

	/** @type {FC.FutureSociety[]} */
	fsNames: [],

	/** @type {FC.FutureSociety[]} */
	playerFSNames: []
};

/* -- auto-populate derived lists from records -- */
App.Data.FutureSociety.fsNames = /** @type {FC.FutureSociety[]} */ (Object.keys(App.Data.FutureSociety.records));
App.Data.FutureSociety.playerFSNames = App.Data.FutureSociety.fsNames.filter(fs => !App.Data.FutureSociety.records[fs].NPCOnly);