<div class="narrative-box">
/* ── NAME ENTRY LIVES ALONE, AND MUST STAY THAT WAY ───────────────────────
A textbox writes its variable as you TYPE, but SugarCube renders a passage
ONCE. So any $name printed in the same passage as the textbox was already
drawn -- with the default still in it -- before the player touched the
keyboard. The intro carried 46 of them, which is why the whole first screen
said "Nathan" until the first click re-rendered somewhere else.
Splitting it is the whole fix: nothing here prints $name, and the prose
passage that follows is not rendered until the names are already set.
DO NOT move prose back into this passage. */
<div style="text-align:center; margin-bottom:24px; padding:14px; border:1px solid #2a1a3a; border-radius:8px; background:#0a0a0a;">
<label style="display:inline-block; margin:0 10px;"><span style="font-size:0.74em; color:#666; display:block; letter-spacing:0.12em; text-transform:uppercase; margin-bottom:3px;">Your name</span><<textbox "$name" "Nathan">></label>
<label style="display:inline-block; margin:0 10px;"><span style="font-size:0.74em; color:#666; display:block; letter-spacing:0.12em; text-transform:uppercase; margin-bottom:3px;">You are their</span><<textbox "$familymale" "stepbrother">></label>
<label style="display:inline-block; margin:0 10px;"><span style="font-size:0.74em; color:#666; display:block; letter-spacing:0.12em; text-transform:uppercase; margin-bottom:3px;">Each of them is your</span><<textbox "$family" "stepsister">></label>
</div>
<img src="img/Characters/Player/Portrait.jpg" style="display:block; margin:0 auto 24px; max-width:200px; border-radius:8px; border:2px solid #333;">
<div style="text-align:center; color:#888; font-size:0.9em; margin-bottom:26px; line-height:1.7;">
Set your names above, then choose how to begin.<br>
<span style="color:#555; font-size:0.9em;">A blank box keeps the name shown in it.</span>
</div>
<div style="text-align:center; display:flex; gap:14px; justify-content:center; flex-wrap:wrap;">
<span class="intro-go">
<<button "Read the intro →">>
/* Fall back to the placeholder if the player cleared a box. An empty
$name would print as nothing at all for the whole game. */
<<if !$name>><<set $name = "Nathan">><</if>>
<<if !$familymale>><<set $familymale = "stepbrother">><</if>>
<<if !$family>><<set $family = "stepsister">><</if>>
<<goto "Intro">>
<</button>>
</span>
<span class="skip-intro">
<<button "Skip the intro →">>
<<if !$name>><<set $name = "Nathan">><</if>>
<<if !$familymale>><<set $familymale = "stepbrother">><</if>>
<<if !$family>><<set $family = "stepsister">><</if>>
<<goto "DayStart">>
<</button>>
</span>
</div>
<div style="text-align:center; color:#555; font-size:0.76em; font-style:italic; margin-top:7px;">Skipping goes straight to the first morning.</div>
<style>
.intro-go button { width:auto !important; display:inline-block !important; margin:0 !important; padding:7px 20px !important; font-size:0.95em !important; background:#12001a; color:#cc9aff; border:1px solid #6a0dad; border-radius:5px; cursor:pointer; }
.intro-go button:hover { background:#2a0a3a; color:#e0b3ff; }
.skip-intro button { width:auto !important; display:inline-block !important; margin:0 !important; padding:7px 20px !important; font-size:0.95em !important; background:#0a0a0a; color:#9a7aaa; border:1px solid #3a2a4a; border-radius:5px; cursor:pointer; }
.skip-intro button:hover { background:#2a0a3a; color:#cc9aff; border-color:#6a0dad; }
</style>
</div>/* =========================================================================
0. LOAD JAVASCRIPT LIBRARIES
========================================================================= */
<<script>>
eval(Story.get("JS-Core").text);
eval(Story.get("JS-Suspicion").text);
eval(Story.get("JS-Nests").text);
eval(Story.get("JS-Roaming").text);
eval(Story.get("JS-Activities").text);
eval(Story.get("JS-Goals").text);
/* JS-Factions was split into four passages. Order matters: Core defines
window.FACTION_CFG and the shared helpers the other three read. */
eval(Story.get("JS-Factions-Core").text);
eval(Story.get("JS-Factions-Clash").text);
eval(Story.get("JS-Factions-Events").text);
eval(Story.get("JS-Factions-Directives").text);
eval(Story.get("JS-Upgrades").text);
eval(Story.get("JS-Scenes").text);
eval(Story.get("JS-Harem").text);
<</script>>
/* =========================================================================
1. CORE GAME STATE
========================================================================= */
<<set $day to 0>>
<<set $parasite to 1>>
<<set $start to "vanilla">>
<<set $storyprogress to 1>>
<<set $daysOfWeek to ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]>>
<<set $weekDay to "Sunday">>
<<set $currentLocation to "House">>
/* Identity & Relationship Labels */
<<set $name to "Nathan">>
<<set $family to "stepsister">>
<<set $familymale to "stepbrother">>
/* ── PLAYER SETTINGS ── */
<<set $settings = {
factionMaxSize: 7,
videoMode: "randomized",
girlsPerScene: 7,
/* Automatic infection. ON by default, so an existing save behaves exactly
as it did. When off, nothing infects a girl unless the player asked for
it -- see window.autoInfectOn() in JS-Core for the full list of what it
gates and, just as importantly, what it does not. */
autoInfect: true
}>>
/* =========================================================================
2. DATA LOADING & ROSTER BUILDING
========================================================================= */
<<include "G1Data">>
<<include "G2Data">>
<<include "G3Data">>
<<include "G4Data">>
<<include "G5Data">>
<<include "G6Data">>
<<include "G7Data">>
<<include "GroupData">>
<<include "LocationData">>
/* ── ROSTER & GROUPS ──────────────────────────────────────────────────────
This used to be the other way round: $groups held hardcoded member lists
and $roster was built by walking them. That made GroupData a second copy
of data already present on every girl (her `group:` field), and a third
copy existed in GOAL_GROUPS.
Now the character records are the source. $roster is built from the girl
objects themselves, and buildGroups() derives $groups and GOAL_GROUPS from
their `group:` fields.
─────────────────────────────────────────────────────────────────────── */
<<script>>
(function () {
var sv = State.variables;
sv.roster = [];
/* Every G*Data passage declares its girls as $<var> with a matching
`var:` field. Collect them in declaration order — the same order the
old nested loop produced, because the data files are included in
group order above. */
Object.keys(sv).forEach(function (k) {
var c = sv[k];
if (c && typeof c === "object" && c.var === k && c.name && c.group) {
sv.roster.push(k);
}
});
window.buildGroups();
})();
<</script>>
/* Initialize Connections array for all characters */
<<script>>
var roster = State.variables.roster;
roster.forEach(function(id) {
if (!State.variables[id].connections) {
State.variables[id].connections = [];
}
});
<</script>>
/* Class Rosters */
<<set $classRosters = {
"Chanel": ["aria","eva","marie","violet","vanna","alex","isabella","ashly"],
"Amber": ["elsa","chloe","melody","scarlet","athena","lacy","nancy","kyler","savannah"],
"Adriana": ["emily","harmony","laila","maya","yulia","kylie","gabbie","ash"],
"Mia": ["jade","adria","rae","demi","caprice","leah","abella","karlee"],
"Veruca": ["blake","vina","kailey","riley","madi","kenzie","haley","avi"],
"Aidra": ["myra","claire","carolina","uma","harley","ariana","jasmine","molly"]
}>>
/* =========================================================================
3. SUSPICION & SECURITY SYSTEMS
========================================================================= */
<<set $suspicion = 0>>
<<set $detectiveActive = false>>
<<set $gameOver = false>>
<<set $todayInfectedByLoc = {}>>
<<set $recentVectorDays = []>>
<<set $blockedLocations = []>>
/* Mechanics Initialization: Nests & Traits */
<<script>>
var locs = State.variables.locations;
var nests = {};
var traits = {};
locs.forEach(function(loc) {
nests[loc.name] = { level: 0, days: 0, type: "spreading", specialisation: null };
traits[loc.name] = loc.trait;
});
nests["Police Station"] = { level: 0, days: 0, type: "spreading", specialisation: null };
nests["The Lab"] = { level: 0, days: 0, type: "spreading", specialisation: null };
traits["Police Station"] = "critical";
traits["The Lab"] = "critical";
State.variables.nests = nests;
window.LOCATION_TRAITS = traits;
<</script>>
<<set $nestSuspReduction = {}>>
<<set $nestDriftBoost = {}>>
/* =========================================================================
4. FACTIONS & SOCIAL STATE
========================================================================= */
<<set $factions = [
{ id: 1, leader: "jewelz", members: ["jewelz","kali"], name: "Jewelz's Friends", corruption: 0, stability: 60, formed: 0, lastStructuralChange: 0, lastEvent: 0, homeLocation: null, locationHistory: [], stance: "neutral", rivalOf: [], playerInfluence: 0, directive: null },
{ id: 2, leader: "elsa", members: ["elsa","melody"], name: "Elsa's Friends", corruption: 0, stability: 60, formed: 0, lastStructuralChange: 0, lastEvent: 0, homeLocation: null, locationHistory: [], stance: "neutral", rivalOf: [], playerInfluence: 0, directive: null },
{ id: 3, leader: "lana", members: ["lana","casey"], name: "Lana's Friends", corruption: 0, stability: 60, formed: 0, lastStructuralChange: 0, lastEvent: 0, homeLocation: null, locationHistory: [], stance: "neutral", rivalOf: [], playerInfluence: 0, directive: null },
{ id: 4, leader: "aria", members: ["aria","ashly"], name: "Aria's Friends", corruption: 0, stability: 60, formed: 0, lastStructuralChange: 0, lastEvent: 0, homeLocation: null, locationHistory: [], stance: "neutral", rivalOf: [], playerInfluence: 0, directive: null },
{ id: 5, leader: "eva", members: ["eva","riley"], name: "Eva's Friends", corruption: 0, stability: 60, formed: 0, lastStructuralChange: 0, lastEvent: 0, homeLocation: null, locationHistory: [], stance: "neutral", rivalOf: [], playerInfluence: 0, directive: null },
{ id: 6, leader: "marie", members: ["marie","blake"], name: "Marie's Friends", corruption: 0, stability: 60, formed: 0, lastStructuralChange: 0, lastEvent: 0, homeLocation: null, locationHistory: [], stance: "neutral", rivalOf: [], playerInfluence: 0, directive: null },
{ id: 7, leader: "lulu", members: ["lulu","molly"], name: "Lulu's Friends", corruption: 0, stability: 60, formed: 0, lastStructuralChange: 0, lastEvent: 0, homeLocation: null, locationHistory: [], stance: "neutral", rivalOf: [], playerInfluence: 0, directive: null },
{ id: 8, leader: "kenzie", members: ["kenzie","madi"], name: "Kenzie's Friends", corruption: 0, stability: 60, formed: 0, lastStructuralChange: 0, lastEvent: 0, homeLocation: null, locationHistory: [], stance: "neutral", rivalOf: [], playerInfluence: 0, directive: null }
]>>
<<set $nextFactionId = 9>>
<<set $pendingParties = []>>
<<set $attendingParty = null>>
<<set $pendingClash = null>>
<<set $attendingClash = null>>
<<set $territoryConflicts = []>>
<<set $factionDirectiveMode = null>>
<<set $factionInfiltrateAgent = null>>
<<set $orderedClashes = []>>
<<set $factionHelpId = null>>
<<set $factionDirectiveId = null>>
/* Group Meeting Pairs */
<<set $groupMeetings = [
{ location: "Neighbor's House", members: ["laila","demi"] },
{ location: "Gym", members: ["alison","leah","abella"] },
{ location: "Cheerleader Track", members: ["athena","lacy"] },
{ location: "Cafeteria", members: ["christie","gina"] },
{ location: "School Pool", members: ["harley","ariana","aidra"] },
{ location: "Town Hall", members: ["nicole","lily"] },
{ location: "Real Estate", members: ["quinn","kenna"] },
{ location: "Restaurant", members: ["kendra","jasmine","katie"] },
{ location: "Student Council", members: ["jade","adria","gabbie"] },
{ location: "Office", members: ["megan","savannah","kyler"] },
{ location: "Club", members: ["avery","lexi","leda"] },
{ location: "Hotel", members: ["momo","autumn","caitlyn","stella"] }
]>>
<<run window.syncFactionConnections()>>
/* =========================================================================
5. INTERACTION & SCENE STATE
========================================================================= */
/* Roaming & Meeting */
<<set $girlLocations = {}>>
<<set $isWeekend = false>>
<<set $meetingTarget = null>>
<<set $meetingIntroducer = null>>
<<set $contactIntroducer = {}>>
<<set $metToday = false>>
<<set $groupMeetingActive = false>>
<<set $groupMeetingRollLoc = "">>
<<set $partyMeetTarget = "">>
<<set $partyMeetIntroducer = "">>
/* Infection Actions */
<<set $infectMethod = "direct">>
<<set $infectVectorSrc = null>>
<<set $levelUpTarget = null>>
<<set $levelUpStage = null>>
<<set $levelUpReturn = null>>
/* SCENE TRACKING (NEW) */
<<set $sceneWatchedToday = false>>
<<set $seenScenes = {}>>
/* Harem Mansion */
<<set $haremUnlocked = false>>
<<set $haremFinancier = null>>
<<set $haremGuests = []>>
<<set $haremPartyToday = false>>
<<set $activeSceneID = "">>
<<set $sceneLocation = null>>
<<set $sceneGroup = []>>
<<set $sceneTier = null>>
<<set $sceneReturn = null>>
/* Faction Suspicion Scenes */
<<set $activeSuspicionAgent = null>>
<<set $activeSuspicionResidents = null>>
<<set $activeSuspicionThreshold = null>>
/* =========================================================================
6. UPGRADE & GOAL SYSTEMS
========================================================================= */
/* ── MISC ── */
<<set $availableActivities = {}>>
<<set $pendingLevelUpScene = null>>
<<set $availableScenes = {}>>
<<set $parasiteLevel = 1>>
<<set $nestCap = 2>>
<<set $hivemindCap = 5>>
<<set $infectionPower = 1>>
/* The two levelled purchases. Their buy branches derive the level from the
legacy booleans when it is undefined, so an old save still works -- these
are here so a NEW save starts explicit rather than derived. */
<<set $corrCapLevel = 0>>
<<set $factionDirectiveLevel = 0>>
<<set $upgrades = {
/* Tier 1 */
characterAgenda: false, locationAgenda: false, revealPortraits: false, locationDiscovery: false, nestDuration1: false, infectionSuccessRate1: false,
/* Tier 2 */
corrCapUnlock1: false, suspicionIntimate: false, suspicionSocialHub: false, suspicionAcademic: false, corrTickSocialHub: false, corrTickIntimate: false, corrTickSameLocation: false, nestDuration2: false, factionDirectives1: false, factionDirectives2: false, factionParasiteGen1: false, noPartySuspicion: false,
/* Tier 3 */
corrCapUnlock2: false, noRandomSuspicion: false, suspicionOutdoor: false, suspicionDecay: false, corrTickGlobal: false, corrTickSocialHub2: false, corrTickIntimate2: false, corrTickSameLocation2: false, nestCritical: false, nestDecayOutdoor: false, infectAuthority: false, noArrest: false, passiveSpread: false, locControlSocialHub: false, locControlAcademic: false, locControlIntimate: false, locControlOutdoor: false, locControlCritical: false, factionDirectives3: false, collectiveWill: false, factionParasiteGen2: false, noActivitySuspicion: false,
/* Tier 4 */
corrCapUnlock3: false, infectUnmet: false, vectors: false, highCorrNoSuspicion: false, globalSuspicionReduce: false, corrTickEverywhere: false, nestBreedingBoost: false, nestsNeverDecay: false, locDominatedSpread: false, factionDirectives4: false, factionAutoSpread: false, factionAutoSpread2: false, factionParasiteGen3: false
}>>
/* Goals */
<<set $goals = []>>
<<set $goalsCompleted = []>>
<<set $goalHistory = {}>>
<<set $goalActionMsg = "">>
<<set $nextGoalId = 100>>
<<set $lastGoalDay = 0>>
<<set $goalBonuses = { upgradeBonus: 0, passiveParasite: 0, noSuspicionIntimate: false, noSuspicionSchool: false, noSuspicionAll: false, corruptedLocations: [] }>>
<<set $capBreakTarget = null>>
<<set $capBreakReturn = null>>
<<set $pendingCaptiveIntro = []>>
<<set $pendingAbductions = []>>
<<set $captives = []>>
<<set $nestProtected = {}>>
/*
=========================================================================
7. FINAL INITIALIZATION
========================================================================= */
<<run window.initGoals()>>[[Characters]]
[[Upgrades]]
[[Goals]]
[[Factions]]
<<if $upgrades && $upgrades.characterAgenda>>[[Character Agenda]]<</if>>
<<if $upgrades && $upgrades.locationAgenda>>[[Location Agenda]]<</if>>
[[Shortcuts]]
[[Tutorial]]
[[Settings]]
[[Cheat]]
<hr>
<<link "Produce Parasite (One Day)">>
<<set $parasite to $parasite + 1>>
<<set $dayLog to ["You produced a parasite."]>>
<<goto "DayEnd">>
<</link>><<set _currentPage to "back" + _currentPage>>
<<nobr>>
<<if _currentPage is not "Intro">>
<span class="navigation-link" onclick="History.back()">Back</span>
<<endif>>
<span class="navigation-link" onclick="History.forward()">Forward</span>
<</nobr>><<set _hideList to ["Age Verification", "Start", "Start2", "Start3", "Start4", "Start5"]>>
<div style="text-align:center;">
<img src="img/Characters/Player/Mini.jpg" style="width:100px; border-radius:50%; border:2px solid #9c27b0;">
</div>
<div style="margin-top:10px; font-size:0.9em;">
<<if $storyprogress > 0>>
<<nobr>>
/* CORE STATS */
Day: <strong style="color:#fff">$day</strong><br>
<strong style="color:#fff">$weekDay</strong><br>
Parasites: <strong style="color:#bd59ff">$parasite</strong><br>
<<set _lvlName = [null,"Hatchling","Juvenile","Mature","Apex"][$parasiteLevel] || "Hatchling">>
Stage: <strong style="color:#bd59ff"><<print _lvlName>></strong> <span style="color:#666;">(<<print $parasiteLevel>>/4)</span><br>
Inf. Power: <strong style="color:#00ff00">$infectionPower</strong><br>
/* Hivemind load — how many girls you are holding against the ceiling.
Infection is blocked at the cap, so this needs to be visible without
opening the Upgrades screen. */
<<set _hmLoad = window.getHivemindLoad ? window.getHivemindLoad() : 0>>
<<set _hmCap = $hivemindCap || 5>>
<<set _hmCol = _hmLoad >= _hmCap ? "#ff5555" : (_hmLoad >= Math.floor(_hmCap * 0.75) ? "#ffcc00" : "#44aaff")>>
Hivemind: <strong @style="'color:' + _hmCol"><<print _hmLoad>>/<<print _hmCap>></strong><<if _hmLoad >= _hmCap>> <span style="color:#ff5555; font-size:0.8em;">FULL</span><</if>><br>
<hr style="border-color:#333; margin:8px 0;">
/* SUSPICION */
<<set _sc to window.getSuspicionColor()>>
<<set _sl to window.getSuspicionLabel()>>
<span style="font-size:0.85em; color:#aaa;">Suspicion:</span><br>
<div style="background:#1a1a1a; border:1px solid #444; border-radius:4px; height:8px; margin:3px 0;">
<div @style="'width:' + $suspicion + '%; height:100%; border-radius:4px; background:' + _sc + '; transition:width 0.4s ease;'"></div>
</div>
<span @style="'color:' + _sc + '; font-weight:bold; font-size:0.9em;'">
<<print _sl>> ($suspicion/100)
</span>
<<if $suspicion > 0 and $parasite >= 3>>
<div style="margin-top:6px;">
<<button "🧬 Cover Tracks (-3pt, -5 susp)">>
<<set $parasite -= 3>>
<<set $suspicion = Math.max(0, $suspicion - 5)>>
<<run UI.update()>>
<</button>>
</div>
<</if>>
<<if $detectiveActive>>
<br><span style="color:#ff8844; font-size:0.78em;">🔍 Detective active</span>
<</if>>
<hr style="border-color:#333; margin:8px 0;">
/* GOALS SUMMARY */
<<if $goals and $goals.length > 0>>
<div style="font-size:0.82em; margin-top:6px;">
<<set _done = $goals.filter(g => window.getGoalProgress(g).pct >= 100).length>>
<span style="color:<<if _done > 0>>#ffcc00<<else>>#555<</if>>; font-weight:<<if _done > 0>>bold<<else>>normal<</if>>;">
🎯 <<print $goals.length>> goal<<if $goals.length isnot 1>>s<</if>>
<<if _done > 0>> · <span style="animation: pulse 1s infinite;"><<print _done>> ready!</span><</if>>
</span>
</div>
<</if>>
<</nobr>>
<</if>>
</div><<back>>
<h1>Known Subjects</h1>
<<nobr>>
<<for _gi to 0; _gi lt $groups.length; _gi++>>
<div class="character-group">
<div class="character-title"><<print $groups[_gi].name>></div>
<div class="menu-grid">
<<for _mi range $groups[_gi].members>>
<<set _mc = State.variables[_mi]>>
<<if _mc.met>>
<<MenuCharacterCard _mi>>
<<elseif $upgrades && $upgrades.revealPortraits>>
<<MenuCharacterCard _mi "grey">>
<</if>>
<</for>>
</div>
</div>
<</for>>
<</nobr>><div class="narrative-box">
He wakes at some hour with no number attached to it, too hot, with the duvet on the floor.
The room is dark and ordinary. The window is open two inches the way he always leaves it. Somewhere down the landing the boiler is doing the thing it does. Nothing has happened.
$name lies still and takes stock, because Jewelz told him to and because he is the kind of person who does what he's told when it's sensible. Head: fine. No sickness, no swimming, no ache behind the eyes. He can count backwards. He knows what day it is.
He is just extremely hot, and his mouth tastes of pennies.
He gets up for water and stands at the kitchen tap in the dark drinking two glasses straight down, and it doesn't touch it. The thirst isn't in his mouth. It's further back, behind the roof of his mouth, in a place he has no name for and can't reach with a glass of water.
The mark on his side is warm. He presses it with two fingers in the dark and it gives, and it is warmer than the skin around it. Definitely. Not-imagining-it warmer.
He should tell Jewelz. He turns to go up and tell her, and stops at the bottom of the stairs.
Tell her what, exactly. //I fell over and now I'm warm.// She's worked a double and she's up at five, and $name has spent nine years being the one who doesn't add to the pile. He goes back to bed.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
The second time he wakes it isn't heat, or it isn't only heat.
He is hard, painfully so, and it has nothing to do with anything. There was no dream leading up to it. He was asleep and then he was awake and his whole body had already decided, the way it hasn't since he was fourteen — that stupid, total, no-negotiation want, arriving out of nothing at three in the morning.
He deals with it. Of course he does. He is nineteen and it's the middle of the night and there is a practical solution to this.
It doesn't work. Not in the sense of failing — it works fine, twice, and afterwards he is lying in the dark with his heart going and it has not gone anywhere at all. The want is still sitting there whole and undiminished, as though he hasn't touched it, as though the last twenty minutes happened to somebody else.
That frightens him more than anything so far. He lies very still and waits for it to fade, and it does not fade, and eventually the sleep comes up over him like water closing.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
Then the dreams start, and they do not stop until morning.
They are not strange. That's the thing he will keep coming back to. There is nothing dreamlike about them at all — no drifting, no odd logic, nothing melting into anything else. They are as solid as the room he is lying in, and they go on and on, one after another, all night.
<video src="img/Characters/Jewelz/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Jewelz first.
He is not resisting it. That's the part. There is no version of this where he is fighting and losing something. He is enjoying it, hugely, the whole way through.
<video src="img/Characters/Elsa/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Then Elsa.
<video src="img/Characters/Emily/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Then Emily.
They come round again. All three of them, in different rooms, in different orders, for hours, and he does not surface between them. He is never once outside it enough to think //this is a dream// — there is no distance to think it from.
And underneath all of it, one flat unbroken note that isn't a thought and isn't a voice. Just a pressure. A direction. A thing pushing the same way over and over, like a hand on the small of his back.
//More. Again. Deeper.//
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
$name wakes on his front with his heart going and the sheet ruined.
The room is grey with early light. Outside somebody's car door goes, and a dog starts up two gardens over, and the ordinariness of it is so total that for a second he thinks he might genuinely be sick.
He gets up. He strips the bed. He takes the sheet down to the machine before anybody is awake, because that at least is a problem with a procedure attached to it, and then he sits on the edge of the bath for a long time with his head in his hands.
He is nineteen. He has had dreams. Everyone has had dreams, and that is not a thing that needs explaining and not a thing you tell anybody, and if it had been a stranger, or a girl from his class, or nobody in particular, he would be embarrassed for ten minutes and get on with his day.
It was Jewelz. It was Elsa. It was ''Emily''.
And it wasn't a flash at the edge of a dream that he half-remembers and can tell himself he's misreading. It was hours of it.
He tries to get hold of the actual content and finds he can't, not really. It comes back the way a fever comes back — in heat and pressure and the certainty of who it was, without a single scene he could set down in order. What's left is not pictures. What's left is that his whole body knows something happened and is entirely unashamed of it, and that he remembers, with total clarity, being happy about it.
He puts his face in his hands and sits there in the cold bathroom and tries to find the shape of the thing that's wrong with him.
Because he knows what wanting somebody feels like. He has a girlfriend. He is not confused about the basic operation of his own body. And he has never once, in nineteen years, looked at any of the three of them and felt anything remotely like that.
It didn't come from him. He is nearly sure of it. Something in him last night was set to a level he has never in his life set it to, and it was not being fussy about where it pointed.
He puts a hand over the mark on his side. Still warm.
He's ill. That's the only place the thinking lands that he can actually stand. A knock on the head, a temperature, a bad night — people have fevers and fever dreams and say mad things at four in the morning and are fine by Tuesday.
He goes downstairs holding on to that.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
Jewelz is already in the kitchen. Of course she is. She's in the doorway with a mug in both hands and she watches him load the machine at twenty past six on a Sunday and says nothing at all for about four seconds, which from Jewelz is an entire speech.
<<speech "Jewelz">>"Did you sleep?"<</speech>>
<<speech "$name">>"Some."<</speech>>
<<speech "Jewelz">>"Sick in the night?"<</speech>>
<<speech "$name">>"No."<</speech>>
<<speech "Jewelz">>"Dizzy? Seeing double? Headache?"<</speech>>
<<speech "$name">>"No. I was hot — properly hot, like the middle of a fever. Window open, covers off, made no difference at all."<</speech>>
She puts the back of her hand against his forehead the way she has since he was eleven, and frowns.
<<speech "Jewelz">>"You're not warm."<</speech>>
<<speech "$name">>"I know I'm not now. I'm telling you what three in the morning was like, not what this is."<</speech>>
<<speech "Jewelz">>"Mm. And the washing?"<</speech>>
<<speech "$name">>"I sweated through the sheet."<</speech>>
It is true, and it lets him not say the rest, and she takes it — but she looks at him a beat longer than she needs to.
<<speech "Jewelz">>"If you're still like this tomorrow you're going to the doctor's, and I'm coming in with you so you actually go in."<</speech>>
<<speech "$name">>"I'd go in."<</speech>>
<<speech "Jewelz">>"You'd sit in the car park for twenty minutes and drive home."<</speech>>
She isn't wrong and they both know it. She finishes her tea, rinses the mug, and starts on the breakfast things with her back to him.
$name looks at her for two seconds too long. Just the ordinary shape of his $family at the sink on a Sunday morning — and something turns over in him, hot and immediate and entirely unwelcome, and it is the exact thing from four hours ago arriving in a lit kitchen while she runs the tap.
He is up and out of the room before he's decided to move.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
He sits in the front room until it stops. It takes longer than it should.
Emily comes down at eight and finds him there with a glass of water he hasn't touched. She puts bread in the toaster and doesn't ask him anything, which he is grateful for right up until she sits down opposite him and looks at him properly.
<<speech "Emily">>"You've got that face."<</speech>>
<<speech "$name">>"What face?"<</speech>>
<<speech "Emily">>"The one where you've decided not to say something."<</speech>>
$name looks at her — and for a fraction of a second it's there again, unwanted and vivid, and he has to physically move his eyes to the window.
She's been in this house a year and four months and she reads a room faster than anyone in it, and he knows exactly where she learned that, and it has never once made him want to put his fist through a wall as badly as it does right now.
<<speech "$name">>"Bad night. Genuinely, that's all it is — I didn't sleep and I feel like I've been hit by a bus."<</speech>>
<<speech "Emily">>"Okay."<</speech>>
<<speech "$name">>"You don't believe me."<</speech>>
<<speech "Emily">>(getting up for the toast) "I said okay."<</speech>>
She butters it, cuts it in half diagonally, and puts one half on a plate in front of him without making anything of it.
He eats the toast. He feels fine. That's what will bother him all the way through Sunday and into Monday morning — he feels completely fine. Rested. Better than he has in weeks, after a night that should have wrecked him.
Something in him slept extremely well.
<div style="text-align:center; margin-top:32px;">[[Monday (1)|Start3]]</div>
</div><div style="text-align: center; margin-top: 10vh;">
<h1 style="color: #ff0000; text-shadow: 0 0 10px #ff0000; font-size: 3em;">ADULT CONTENT WARNING</h1>
<div class="narrative" style="max-width: 600px; margin: 0 auto; border: 2px solid #444; padding: 30px; background: #0a0a0a; line-height: 1.8;">
<p style="font-weight: bold; color: #eee;">This game contains adult content intended for mature audiences only.
All characters depicted are 18 years of age or older
All characters and events are entirely fictional
Any resemblance to real persons is purely coincidental.</p>
<p>By clicking "ENTER" below, you certify that you are at least <strong>18 years of age</strong> (or the legal age of adulthood in your jurisdiction) and that you consent to viewing adult themes.</p>
<p style="color: #888; font-size: 0.9em;">If you are under 18 or easily offended by the themes described, please exit now.</p>
</div>
<div style="margin-top: 40px; display: flex; justify-content: center; gap: 30px;">
<span class="custom-link" style="font-size: 1.5em;">
[[ENTER|Start]]
</span>
<span style="font-size: 1.5em;">
<a href="https://www.google.com" style="color: #666 !important;">EXIT</a>
</span>
</div>
</div>/* =========================================================================
GROUP DEFINITIONS — the single source of truth for groups
-------------------------------------------------------------------------
This passage used to hold $groups: seven objects each with a hardcoded
`members` array. The same 94 names were ALSO written out in
window.GOAL_GROUPS (JS-Goals) and again as a `group:` field on every girl
in G1Data-G7Data — three lists that had to be edited in lockstep, plus two
more partial copies (SCHOOL_GROUPS in JS-Roaming, _groupOrder in
HaremPartyPicker).
Now there is exactly ONE place a girl's group is recorded: the `group:`
field on her own record. Everything else is derived from the roster at
StoryInit by window.buildGroups().
To add a girl to a group, set her `group:` field. That is all.
To add a NEW group, add an entry here.
========================================================================= */
<<script>>
window.GROUP_DEFS = [
{
id: "G1",
label: "Family",
haremPull: true, /* roams to the mansion once unlocked */
school: true, /* counts as a school-going group for roaming */
reward: "passiveParasite"
},
{
id: "G2",
label: "Core Support System",
haremPull: true,
school: true,
reward: "noSuspicionIntimate"
},
{
id: "G3",
label: "Close School Friends",
haremPull: false,
school: true,
reward: "permanentSchoolNest"
},
{
id: "G4",
label: "School Acquaintances",
haremPull: false,
school: true,
reward: "dominateSchool"
},
{
id: "G5",
label: "School Authority Figures",
haremPull: false,
school: true,
reward: "noSuspicionSchool"
},
{
id: "G6",
label: "Town Folks",
haremPull: false,
school: false,
reward: "dominateBusiness"
},
{
id: "G7",
label: "Public Figures",
haremPull: false,
school: false,
reward: "suspicionZero"
}
];
/* ── LOOKUPS ─────────────────────────────────────────────────────────────
A girl's `group:` field may hold either the id ("G1") or the label
("Family"). Both resolve to the same definition, so the existing
character records keep working untouched and new/mod girls can use
whichever they find clearer.
────────────────────────────────────────────────────────────────────── */
window.getGroupDef = function(key) {
if (!key) return null;
var defs = window.GROUP_DEFS;
for (var i = 0; i < defs.length; i++) {
if (defs[i].id === key || defs[i].label === key) return defs[i];
}
return null;
};
/* The display label for whatever a girl has in her `group:` field.
An unrecognised value (a mod's own group) is shown as-is rather than
dropped, so a modded girl never appears group-less. */
window.getGroupLabel = function(key) {
var def = window.getGroupDef(key);
return def ? def.label : (key || "Unaffiliated");
};
window.getGroupId = function(key) {
var def = window.getGroupDef(key);
return def ? def.id : (key || "");
};
/* ── DERIVE MEMBERSHIP FROM THE ROSTER ───────────────────────────────────
Called once from StoryInit, after the character data has loaded. Walks
every girl, reads her `group:` field and builds:
$groups [{ id, name, members }] — Characters, Character Agenda,
HaremPartyPicker ordering
GOAL_GROUPS { G1: { label, members } } — group goals
Any group a girl declares that isn't in GROUP_DEFS is appended at the end
as a custom group with no reward and no harem pull. That is the hook mod
girlpacks will use.
────────────────────────────────────────────────────────────────────── */
/* ── DISPLAY ORDER WITHIN A GROUP ────────────────────────────────────────
Membership is still derived from each girl's `group:` field — this is
NOT a second copy of the roster, and nothing here decides who is in what
group. It only decides what order they are listed in.
Girls used to appear in whatever order the G*Data passages happened to
declare them, which was neither alphabetical nor meaningful. They are now
grouped by relationship and by where you actually find them, so the
Characters page reads as a description of $name's life rather than a dump.
A girl missing from this list still shows up — she is simply placed after
everyone listed, in declaration order. That is what makes it safe for mods
and for new characters: forget to add someone and the page still works.
────────────────────────────────────────────────────────────────────── */
window.GROUP_MEMBER_ORDER = {
/* Eldest first, then the two who live with him, then the cousins. */
"G1": ["jewelz", "elsa", "winter", "emily", "kylie", "lana"],
/* Girlfriend, best friend, the classmates he is closest to, his own
dorm, the godmother's house, the twins next door. */
"G2": ["aria", "eva",
"marie", "isabella", "kailey",
"karlee", "claire", "scarlet",
"melissa", "vina",
"demi", "laila"],
/* Aria and Eva's circle first, then his own classmates, Marie's dorm,
the student council, the sorority, then the mansion and the office. */
"G3": ["violet", "ashly", "vanna", "riley", "harmony",
"maya", "alex", "melody", "caprice",
"blake", "myra",
"gabbie", "adria", "jade", "nancy",
"haley",
"savannah", "kyler"],
/* Cheer squad, the gym, the pool, the restaurant, the cinema pair,
classroom acquaintances, the library, the sorority, the arcade. */
"G4": ["athena", "lacy",
"leah", "abella",
"ariana", "harley", "uma", "carolina", "jasmine",
"molly", "lulu",
"yulia", "ash", "chloe", "rae",
"natalie", "avi",
"kenzie", "madi"],
/* Professors, then the specialists, then the staff who keep it running. */
"G5": ["chanel", "adriana", "amber", "veruca", "mia",
"aidra", "shazia", "anya",
"christie", "gina"],
/* The mall, the gym and spa, the restaurant, the hotel, the office and
the agency, the club, and the two at the top of the hill. */
"G6": ["kali", "skylar", "kate", "natalia", "may",
"alison", "alina", "nikki",
"kendra", "katie",
"caitlyn", "stella", "autumn", "momo",
"megan", "quinn", "kenna",
"avery", "lexi", "leda",
"luna", "casey"],
/* The station, the town hall, the courthouse. */
"G7": ["ember", "angel", "jane",
"nicole", "lily", "keisha",
"jessa"]
};
/* Sort a member array into GROUP_MEMBER_ORDER. Anyone not listed keeps her
relative position and goes to the end. */
window.sortGroupMembers = function(gid, members) {
var order = (window.GROUP_MEMBER_ORDER || {})[gid];
if (!order) return members;
var rank = {};
order.forEach(function(id, i) { rank[id] = i; });
var big = order.length;
return members.slice().sort(function(a, b) {
var ra = rank[a] === undefined ? big + members.indexOf(a) : rank[a];
var rb = rank[b] === undefined ? big + members.indexOf(b) : rank[b];
return ra - rb;
});
};
window.buildGroups = function() {
var sv = State.variables;
var order = [];
var byId = {};
/* Seed with the defined groups so they always appear in this order,
even if a group happens to have no members yet. */
window.GROUP_DEFS.forEach(function(def) {
byId[def.id] = { id: def.id, name: def.label, members: [] };
order.push(def.id);
});
(sv.roster || []).forEach(function(id) {
var c = sv[id];
if (!c) return;
var def = window.getGroupDef(c.group);
var gid = def ? def.id : (c.group || "Unaffiliated");
if (!byId[gid]) {
/* Custom group declared by a girl (a mod, or a typo). */
byId[gid] = { id: gid, name: c.group || "Unaffiliated", members: [], custom: true };
order.push(gid);
}
byId[gid].members.push(id);
});
/* Put each group's members into their display order before anything
reads them. $groups feeds the Characters page, Character Agenda and
the harem picker, so all three get the ordering for free. */
order.forEach(function(gid) {
byId[gid].members = window.sortGroupMembers(gid, byId[gid].members);
});
sv.groups = order.map(function(gid) { return byId[gid]; });
/* GOAL_GROUPS is the same data keyed by id. Groups with no members are
excluded — an empty group goal would complete instantly. */
window.GOAL_GROUPS = {};
sv.groups.forEach(function(g) {
if (!g.members.length) return;
window.GOAL_GROUPS[g.id] = { label: g.name, members: g.members };
});
return sv.groups;
};
/* Convenience predicates, replacing the hardcoded name lists that used to
live in JS-Harem and JS-Roaming. */
window.groupHasHaremPull = function(key) {
var def = window.getGroupDef(key);
return !!(def && def.haremPull);
};
window.groupIsSchool = function(key) {
var def = window.getGroupDef(key);
return !!(def && def.school);
};
/* ── IS SHE A STUDENT? ───────────────────────────────────────────────────
The single predicate for "attends this school as a pupil". Two systems
need it and used to answer it differently, from two hand-written name
lists that drifted apart:
JS-Roaming NON_STUDENTS — who may be dropped into School/Dorms
locations she has no scheduled reason to be at
JS-Activities detStudents — who can be sent to detention
Both now call this.
The rule is data, not a roster:
1. her group must be flagged `school` in GROUP_DEFS
2. School Authority Figures supervise rather than attend
3. `student: false` on her own record overrides 1 — for the handful of
adults who belong to a school group socially (Jewelz, Lana, Winter,
Melissa) without being pupils
A mod girl needs nothing: declaring a school group makes her a student,
and adding `student: false` makes her an adult in that circle. */
window.isStudent = function(who) {
var c = (typeof who === "string") ? State.variables[who] : who;
if (!c) return false;
if (c.student === false) return false;
if (c.group === "School Authority Figures") return false;
return window.groupIsSchool(c.group);
};
<</script>><<widget "CharacterVideos">><<nobr>>
<<set _cv = _args[0]>>
<<set _c = State.variables[_cv]>>
<<set _n = window.getCharFolderName(_c.name)>>
<<set _mode = ($settings && $settings.videoMode) ? $settings.videoMode : "randomized">>
<<set _t1ok = _c.corr >= 25>>
<<set _t2ok = _c.corr >= 50>>
<<set _t3ok = _c.corr >= 75>>
<<if _mode is "last1">>
<<if _t3ok>><<set _t1ok = false>><<set _t2ok = false>>
<<elseif _t2ok>><<set _t1ok = false>><<set _t3ok = false>>
<</if>>
<<elseif _mode is "last2">>
<<if _t3ok and _t2ok>><<set _t1ok = false>><</if>>
<</if>>
<<if _t1ok>>
<<if _mode is "primary">>
/* Primary clip type only — Mast at tier 1, one at random. */
<<set _idx = random(1, 3)>>
<video @src="'img/Characters/' + _n + '/1/Mast' + _idx + '.mp4'" width="100%" autoplay controls loop muted></video>
<<elseif _mode is "randomized">>
/* One clip at random from the WHOLE tier, not one Mast clip.
Tier 1 is 3 Mast + 3 HJ, so roll 1-6 and let 4-6 be HJ. */
<<set _pick = random(1, 6)>>
<<if _pick lte 3>>
<video @src="'img/Characters/' + _n + '/1/Mast' + _pick + '.mp4'" width="100%" autoplay controls loop muted></video>
<<else>>
<video @src="'img/Characters/' + _n + '/1/HJ' + (_pick - 3) + '.mp4'" width="100%" autoplay controls loop muted></video>
<</if>>
<<else>>
<<for _idx to 1; _idx lte 3; _idx++>>
<video @src="'img/Characters/' + _n + '/1/Mast' + _idx + '.mp4'" width="100%" autoplay controls loop muted style="margin-bottom:6px;"></video>
<</for>>
<<for _idx to 1; _idx lte 3; _idx++>>
<video @src="'img/Characters/' + _n + '/1/HJ' + _idx + '.mp4'" width="100%" autoplay controls loop muted style="margin-bottom:6px;"></video>
<</for>>
<</if>>
<</if>>
<<if _t2ok>>
<<if _mode is "primary">>
/* Primary clip type only — BJ at tier 2. */
<<set _idx = random(1, 4)>>
<video @src="'img/Characters/' + _n + '/2/BJ' + _idx + '.mp4'" width="100%" autoplay controls loop muted></video>
<<elseif _mode is "randomized">>
/* Tier 2 is 4 BJ + 3 Cum, so roll 1-7 and let 5-7 be Cum. */
<<set _pick = random(1, 7)>>
<<if _pick lte 4>>
<video @src="'img/Characters/' + _n + '/2/BJ' + _pick + '.mp4'" width="100%" autoplay controls loop muted></video>
<<else>>
<video @src="'img/Characters/' + _n + '/2/Cum' + (_pick - 4) + '.mp4'" width="100%" autoplay controls loop muted></video>
<</if>>
<<else>>
<<for _idx to 1; _idx lte 4; _idx++>>
<video @src="'img/Characters/' + _n + '/2/BJ' + _idx + '.mp4'" width="100%" autoplay controls loop muted style="margin-bottom:6px;"></video>
<</for>>
<<for _idx to 1; _idx lte 3; _idx++>>
<video @src="'img/Characters/' + _n + '/2/Cum' + _idx + '.mp4'" width="100%" autoplay controls loop muted style="margin-bottom:6px;"></video>
<</for>>
<</if>>
<</if>>
<<if _t3ok>>
<<if _mode is "primary">>
/* Primary clip type only — Sex at tier 3. */
<<set _idx = random(1, 4)>>
<video @src="'img/Characters/' + _n + '/3/Sex' + _idx + '.mp4'" width="100%" autoplay controls loop muted></video>
<<elseif _mode is "randomized">>
/* This was the odd one out: it played a Sex clip AND a Creampie
clip, while tiers 1 and 2 played one. Tier 3 is 4 Sex + 2
Creampie, so roll 1-6 and let 5-6 be Creampie. */
<<set _pick = random(1, 6)>>
<<if _pick lte 4>>
<video @src="'img/Characters/' + _n + '/3/Sex' + _pick + '.mp4'" width="100%" autoplay controls loop muted></video>
<<else>>
<video @src="'img/Characters/' + _n + '/3/Creampie' + (_pick - 4) + '.mp4'" width="100%" autoplay controls loop muted></video>
<</if>>
<<else>>
<<for _idx to 1; _idx lte 4; _idx++>>
<video @src="'img/Characters/' + _n + '/3/Sex' + _idx + '.mp4'" width="100%" autoplay controls loop muted style="margin-bottom:6px;"></video>
<</for>>
<<for _idx to 1; _idx lte 2; _idx++>>
<video @src="'img/Characters/' + _n + '/3/Creampie' + _idx + '.mp4'" width="100%" autoplay controls loop muted style="margin-bottom:6px;"></video>
<</for>>
<</if>>
<</if>>
<</nobr>><</widget>>
<<widget "GroupVideos">><<nobr>>
<<set _gvList = _args[0]>>
<<set _mode = ($settings && $settings.videoMode) ? $settings.videoMode : "randomized">>
<<set _gvRolls = []>>
/* ── PRE-ROLL: build per-girl clip data and tier flags ── */
<<for _gi to 0; _gi lt _gvList.length; _gi++>>
<<set _gvc = State.variables[_gvList[_gi]]>>
<<set _t1 = _gvc.corr >= 25>>
<<set _t2 = _gvc.corr >= 50>>
<<set _t3 = _gvc.corr >= 75>>
<<if _mode is "last1">>
<<if _t3>><<set _t1 = false>><<set _t2 = false>>
<<elseif _t2>><<set _t1 = false>><<set _t3 = false>>
<</if>>
<<elseif _mode is "last2">>
<<if _t3 and _t2>><<set _t1 = false>><</if>>
<</if>>
<<set _gvRolls.push({
name: window.getCharFolderName(_gvc.name),
t1: _t1,
t2: _t2,
t3: _t3,
mastIdx: Math.floor(Math.random() * 3) + 1,
hjIdx: Math.floor(Math.random() * 3) + 1,
bjIdx: Math.floor(Math.random() * 4) + 1,
cumIdx: Math.floor(Math.random() * 3) + 1,
sexIdx: Math.floor(Math.random() * 4) + 1,
cpIdx: Math.floor(Math.random() * 2) + 1,
/* Randomized mode picks one clip from the WHOLE tier rather than
always taking the first clip type. Tier 1 is 3 Mast + 3 HJ,
tier 2 is 4 BJ + 3 Cum, tier 3 is 4 Sex + 2 Creampie. */
p1: Math.floor(Math.random() * 6) + 1,
p2: Math.floor(Math.random() * 7) + 1,
p3: Math.floor(Math.random() * 6) + 1
})>>
<</for>>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:10px;">
/* ── TIER 1 PASS: one clip per girl who has tier 1 ── */
<<for _r range _gvRolls>><<capture _r>>
<<if _r.t1>>
<<if _mode is "primary">>
<video @src="'img/Characters/' + _r.name + '/1/Mast' + _r.mastIdx + '.mp4'" width="100%" autoplay loop muted></video>
<<elseif _mode is "randomized">>
<<if _r.p1 lte 3>>
<video @src="'img/Characters/' + _r.name + '/1/Mast' + _r.p1 + '.mp4'" width="100%" autoplay loop muted></video>
<<else>>
<video @src="'img/Characters/' + _r.name + '/1/HJ' + (_r.p1 - 3) + '.mp4'" width="100%" autoplay loop muted></video>
<</if>>
<<else>>
<video @src="'img/Characters/' + _r.name + '/1/Mast' + _r.mastIdx + '.mp4'" width="100%" autoplay loop muted></video>
<video @src="'img/Characters/' + _r.name + '/1/HJ' + _r.hjIdx + '.mp4'" width="100%" autoplay loop muted></video>
<</if>>
<</if>>
<</capture>><</for>>
/* ── TIER 2 PASS: one clip per girl who has tier 2 ── */
<<for _r range _gvRolls>><<capture _r>>
<<if _r.t2>>
<<if _mode is "primary">>
<video @src="'img/Characters/' + _r.name + '/2/BJ' + _r.bjIdx + '.mp4'" width="100%" autoplay loop muted></video>
<<elseif _mode is "randomized">>
<<if _r.p2 lte 4>>
<video @src="'img/Characters/' + _r.name + '/2/BJ' + _r.p2 + '.mp4'" width="100%" autoplay loop muted></video>
<<else>>
<video @src="'img/Characters/' + _r.name + '/2/Cum' + (_r.p2 - 4) + '.mp4'" width="100%" autoplay loop muted></video>
<</if>>
<<else>>
<video @src="'img/Characters/' + _r.name + '/2/BJ' + _r.bjIdx + '.mp4'" width="100%" autoplay loop muted></video>
<video @src="'img/Characters/' + _r.name + '/2/Cum' + _r.cumIdx + '.mp4'" width="100%" autoplay loop muted></video>
<</if>>
<</if>>
<</capture>><</for>>
/* ── TIER 3 PASS: one clip per girl who has tier 3 ── */
<<for _r range _gvRolls>><<capture _r>>
<<if _r.t3>>
<<if _mode is "primary">>
<video @src="'img/Characters/' + _r.name + '/3/Sex' + _r.sexIdx + '.mp4'" width="100%" autoplay loop muted></video>
<<elseif _mode is "randomized">>
<<if _r.p3 lte 4>>
<video @src="'img/Characters/' + _r.name + '/3/Sex' + _r.p3 + '.mp4'" width="100%" autoplay loop muted></video>
<<else>>
<video @src="'img/Characters/' + _r.name + '/3/Creampie' + (_r.p3 - 4) + '.mp4'" width="100%" autoplay loop muted></video>
<</if>>
<<else>>
<video @src="'img/Characters/' + _r.name + '/3/Sex' + _r.sexIdx + '.mp4'" width="100%" autoplay loop muted></video>
<video @src="'img/Characters/' + _r.name + '/3/Creampie' + _r.cpIdx + '.mp4'" width="100%" autoplay loop muted></video>
<</if>>
<</if>>
<</capture>><</for>>
</div>
<</nobr>><</widget>>/* Widget: charLink (Inline Text Link) */
<<widget "charLink">><<nobr>>
<<set _id = _args[0]>>
<<set _txt = _args[1] || State.variables[_id].name>>
<span class="char-link-trigger" @onclick="'window.showCharPopup(\'' + _id + '\''+')'">
<<print _txt>>
</span>
<</nobr>><</widget>>
/* Widget: MenuCharacterCard (Used in Menu) */
<<widget "MenuCharacterCard">><<nobr>>
<<set _cvar = _args[0]>>
<<set _c = State.variables[_cvar]>>
<<if _c.met>>
<<set _imgSrc to window.getPortraitPath(_c.name)>>
<<set _inf = !!_c.infected>>
<div @class="'menu-char-card' + (_inf ? ' infected' : '')">
<div class="menu-char-portrait" @style="'background-image: url(' + _imgSrc + ')'"></div>
<div class="menu-char-info">
<div class="menu-char-name"><<if _inf>><img src="img/Misc/Parasite.jpg" class="menu-char-mark" alt="" /><</if>><<charLink _cvar>></div>
<div class="menu-char-bar-bg">
<div class="menu-char-bar-fill" @style="'width:' + _c.corr + '%'"></div>
</div>
</div>
</div>
<<else>>
<div class="menu-char-card" style="opacity:0.25; filter:grayscale(1); pointer-events:none;">
<div class="menu-char-portrait" style="background:#111; display:flex; align-items:center; justify-content:center;">
<span style="font-size:2em; color:#333;">?</span>
</div>
<div class="menu-char-info">
<div class="menu-char-name" style="color:#333;">???</div>
<div class="menu-char-bar-bg">
<div class="menu-char-bar-fill" style="width:0%"></div>
</div>
</div>
</div>
<</if>>
<</nobr>><</widget>>
/* Widget: CharacterCard (Used in Hub/Location Grid) */
<<widget "CharacterCard">><<nobr>>
<<set _cvar = _args[0]>>
<<set _c = State.variables[_cvar]>>
<<set _imgSrc to window.getImagePath(_c.name, 'portrait')>>
<div class="loc-char-card">
<div class="loc-char-portrait" @style="'background-image: url(' + _imgSrc + ')'">
<div class="loc-bar-container">
<div class="loc-bar-fill" @style="'width:' + _c.corr + '%'"></div>
</div>
</div>
<div class="loc-char-name"><<charLink _cvar>></div>
</div>
<</nobr>><</widget>><div class="narrative-box">
Sunday passes and nothing happens, which by Sunday evening $name has decided to treat as the end of it.
He does the bathroom window. He cooks, badly, and Elsa reheats half of it without saying anything. He goes to bed at eleven expecting the worst and sleeps straight through, no dreams at all, and wakes on Monday feeling ordinary.
The mark on his side is a thin pink line and it is the same temperature as the rest of him. He checks twice.
So: a knock on the head and a bad night. He walks to the school with Emily and Elsa and lets Elsa talk at him about a party at the weekend, and by the time they split at the gates he has almost stopped thinking about it.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
Chanel's class is second period, and $name has been in it for two years with more or less the same twenty people.
<<charLink "eva" "Eva">> normally sits next to him — she has since the first week, on the grounds that she got there first and he can take it up with management — but she isn't in today, and neither is <<charLink "aria" "Aria">>, which is the kind of coincidence that will get him grief later from both of them separately.
So he's on the end of a row with an empty chair beside him, which is how the morning ends up going the way it does.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Marie')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Marie</div></div>
<<charLink "marie" "Marie">> is two seats along, already set up, pen and highlighter lined up parallel because Marie is like that.
<<speech "Marie">>"Where's Eva?"<</speech>>
<<speech "$name">>"No idea. She'll have overslept and she'll blame the bus."<</speech>>
<<speech "Marie">>"She always blames the bus."<</speech>>
<<speech "$name">>"The bus is very unlucky."<</speech>>
He's known Marie since they were fourteen. There was a stretch around sixteen where he had an enormous and completely obvious crush on her, which she handled with more grace than he deserved, and which resolved itself the way those things do. She's been with <<charLink "blake" "Blake">> for a year and a half now and $name likes Blake, and the whole thing is so thoroughly over that it's a joke between them.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Isabella')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Isabella</div></div>
<<charLink "isabella" "Isabella">> drops into the seat in front, turns around backwards over the chair, and puts a folder down.
<<speech "Isabella">>"Right. Say yes before I've asked."<</speech>>
<<speech "$name">>"No."<</speech>>
<<speech "Isabella">>"The squad's doing the thing at the end of the month and the frame for the banner is broken again — the joint at the top, where it always goes."<</speech>>
<<speech "$name">>"That's because it's screwed into chipboard. It'll keep going until somebody spends more than 5 minutes fixing it."<</speech>>
<<speech "Isabella">>"Yes. Wonderful. Could you be the somebody."<</speech>>
<<speech "$name">>"Thursday. Bring it to the workshop, don't make me carry it across the field again."<</speech>>
<<speech "Isabella">>"You're an angel and I'm putting your name on the programme."<</speech>>
<<speech "$name">>"Don't put my name on the programme."<</speech>>
Isabella has been a friend since before he can properly date it — she is one of the lead cheerleaders and takes it more seriously than anyone outside the squad understands, and she has been extracting favours from him on that basis for years.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Vanna')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Vanna</div></div>
<<charLink "vanna" "Vanna">> arrives late, as usual, and sits down heavily in the empty chair next to him with the air of somebody doing it a favour.
<<speech "Vanna">>"This seat free?"<</speech>>
<<speech "$name">>"You're already in it."<</speech>>
<<speech "Vanna">>"I'm being polite."<</speech>>
<<speech "$name">>"You're really not."<</speech>>
<<speech "Vanna">>(entirely unbothered) "No. Have you done the reading?"<</speech>>
<<speech "$name">>"Some of it."<</speech>>
<<speech "Vanna">>"Which some?"<</speech>>
<<speech "$name">>"The some at the beginning."<</speech>>
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Chanel')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Chanel</div></div>
Professor <<charLink "chanel" "Chanel">> comes in at five past and the room reorganises itself without being asked, which is an effect she has. She puts her bag down, writes two words on the board, and starts.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
It happens eleven minutes in.
$name is writing. Vanna leans over to see what page they're on, close enough that her hair swings forward, and the classroom goes.
<video src="img/Characters/Vanna/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
It is not a flash. It is not an intrusive thought or an image at the corner of his eye. For something between two and three seconds he is not in the classroom at all, and he cannot follow it — it is too much at once and too close and it is gone before he can take hold of any part of it. All he keeps is that it was her, and how much of it there was.
Then he is back and the pen is still in his hand and Chanel is still talking and Vanna is saying:
<<speech "Vanna">>"Page four. Are you deaf?"<</speech>>
<<speech "$name">>"Sorry. Four."<</speech>>
<<speech "Vanna">>"You've gone a funny colour."<</speech>>
<<speech "$name">>"I'm fine."<</speech>>
He is not fine. His heart is going hard enough that he can feel it in his hands, and it has left something behind — a heat sitting low in him that has not decided to leave.
He looks at the page and doesn't read it and tells himself, very firmly, that he is nineteen and tired and this is what happens.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
Marie asks him something four minutes later, leaning back with her pen against her jaw, and it happens again.
<video src="img/Characters/Marie/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
And this one is worse, because Marie is not somebody he can be casual about. There was a whole year of his life spent trying not to look at her, and he had thought that was finished and buried.
He loses the room for longer this time. He comes back with his ears hot and no account of what he has just been shown, only the certainty that it was nothing he has ever let himself think about her — that whatever produced it did not consult him, and did not need to.
<<speech "Marie">>"$name."<</speech>>
<<speech "$name">>"What? Sorry."<</speech>>
<<speech "Marie">>"I asked if you had a spare highlighter. You just stared at me for about five seconds."<</speech>>
<<speech "$name">>"I didn't sleep. I've got — I think I've got a temperature."<</speech>>
<<speech "Marie">>(more gently) "You do look rough, actually."<</speech>>
She goes back to her notes. $name sits with both hands flat on the desk and breathes.
It is not the dreams. That is what he keeps arriving at and can't get past. The dreams were at night and asleep and could be filed under //bad night//. This is Monday morning in a lit classroom with a pen in his hand, and it is happening //while he is awake//, and he cannot stop it or see it coming.
Isabella turns round in front of him to say something about Thursday.
<video src="img/Characters/Isabella/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Three seconds. Isabella, who he has known since he was a kid, who once broke her wrist and made him promise not to tell her mother.
He doesn't catch any of it. That is somehow the worst part — it is not a fantasy he could own up to and be embarrassed about, because he isn't in it enough to have made it. It happens at him. Then it stops and she is still talking about Thursday.
He doesn't hear a word she says. She waits, frowns, waves a hand in front of his face.
<<speech "Isabella">>"Hello? Thursday. Workshop. You said."<</speech>>
<<speech "$name">>"Yeah. Thursday. I've got it."<</speech>>
<<speech "Isabella">>"You've got a face like you've seen something."<</speech>>
<<speech "$name">>"I really haven't."<</speech>>
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
By the halfway point $name has stopped writing entirely and is running a count in his head, which is the moment the morning stops being an odd day and becomes something wrong with him.
It isn't tiredness. Tiredness doesn't do this. Tiredness makes you stupid, it doesn't hand you three complete strangers wearing the faces of your friends.
He is halfway into deciding to leave the room when Chanel says his name.
<<speech "Chanel">>"$name. The second point on the board — what's wrong with it?"<</speech>>
He looks up. She is standing by the board with the marker in her hand, waiting, in the specific way she waits — not unkind, but with no intention whatsoever of letting him off.
<video src="img/Characters/Chanel/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
It takes the room away with her still holding the marker, and it is longer than the others, and he understands none of it except that it is happening and that it involves her. When it lets go he has no idea how long the silence has been running.
<<speech "Chanel">>"Take your time."<</speech>>
<<speech "$name">>"It — it assumes the conclusion. It's got the result in the premise."<</speech>>
A beat. Somebody behind him shifts.
<<speech "Chanel">>"Yes. It does. Thank you."<</speech>>
She turns back to the board. $name sits with his ears roaring and understands, with total clarity, that he got that right by accident and that he could not repeat a single thing said in this room in the last twenty minutes.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
He is out of the door about four seconds after the end of the lesson.
Vanna calls something after him and he doesn't turn round. He gets to the end of the corridor and into the stairwell where nobody goes between lessons and stands with his back against the cold wall and his eyes shut.
Four of them. Four, in one room, in fifty minutes.
$name is not a person who panics. He is the one who gets the toolbox and works out what's actually broken. So he stands in the stairwell and tries to do that, and every route he takes arrives somewhere he can't accept.
Stress. He isn't stressed. Sunday was fine.
Tiredness. He slept nine hours and woke up rested.
Some ordinary nineteen-year-old thing that everybody has and nobody mentions. Except that he has been nineteen for eight months and this started, exactly and precisely, the night after he fell over in a wood.
That last one keeps coming back and he keeps putting it down, because the shape of the thought is absurd. He fell over. He hit his head. Things happen to your head. That is a real thing that happens to people, and it is not the same as //something is doing this to me//, and the second one is not a thought a sane person has in a stairwell on a Monday.
He is going to see the doctor. He decides it properly, standing there, in the way he decides things — that if it happens once more he's going, and he'll let Jewelz come in with him, and he'll say the words out loud even though he has absolutely no idea what the words are.
Then the bell goes for third period and he peels himself off the wall and goes to it, because that is what you do.
He gets through the rest of the day without incident. He tells himself that means something.
<div style="text-align:center; margin-top:32px;">[[The end of the day (1)|Start4]]</div>
</div><div class="narrative-box">
Last period finishes and $name is out of the building before the corridor fills up, which is not something he has ever needed to do before.
He gets as far as the bike racks. It is a good afternoon, warm for the time of year, and the front lawn is covered in people in no hurry to go anywhere — and it occurs to him, standing there with his bag over one shoulder, that he has spent the entire day since second period arranging his own movements around the possibility of being near somebody.
That is a mad way to live. He knows it while he is doing it.
He almost gets away.
<<speech "Eva">>"$name!"<</speech>>
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Eva')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Eva</div></div>
<<charLink "eva" "Eva">> comes across the grass at speed with her bag swinging and an expression of enormous grievance. She has been his best friend since they were eleven and she has never once approached him quietly.
<<speech "Eva">>"You didn't text me back. Four times."<</speech>>
<<speech "$name">>"You weren't in. Were you actually ill, or were you asleep?"<</speech>>
<<speech "Eva">>"I was asleep, and then I was ill about it. What did Chanel set?"<</speech>>
<<speech "$name">>"Nothing. She talked about the reading and asked me a question I couldn't answer."<</speech>>
<<speech "Eva">>"You always know the answer."<</speech>>
<<speech "$name">>"Not today."<</speech>>
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Violet')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Violet</div></div>
<<charLink "violet" "Violet">> arrives the way weather arrives, drops her bag against the rack and leans on $name's shoulder with her whole weight.
<<speech "Violet">>"I have had the single worst afternoon of my entire life."<</speech>>
<<speech "Eva">>"What happened?"<</speech>>
<<speech "Violet">>"I don't want to talk about it."<</speech>>
<<speech "Eva">>"You brought it up."<</speech>>
<<speech "Violet">>"I brought it up so you'd know I'd had it. Not so we could //discuss// it."<</speech>>
<<speech "Eva">>"That's not how conversation works, Violet."<</speech>>
<<speech "Violet">>"It's how mine works."<</speech>>
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Aria')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Aria</div></div>
<<charLink "aria" "Aria">> comes down the steps a minute later and takes in the arrangement — Violet attached to her boyfriend's shoulder, Eva with her arms folded — with the mild interest of somebody who has seen it a hundred times.
<<speech "Aria">>"You're all standing in the middle of the path."<</speech>>
<<speech "Violet">>"We're having a crisis."<</speech>>
<<speech "Aria">>"Whose?"<</speech>>
<<speech "Violet">>"Mine. Obviously."<</speech>>
<<speech "Aria">>"Are you going to let go of him at any point?"<</speech>>
<<speech "Violet">>"No."<</speech>>
<<speech "Aria">>"Fair enough."<</speech>>
Aria gets to him and puts a hand flat on his chest in the offhand way she does, more greeting than affection, and kisses him briefly with Violet still hanging off his other side.
This is a completely normal Monday. All four of them have been standing in some version of this arrangement since they were fifteen.
<<speech "Eva">>"Right — Thursday. Are we all pretending Thursday isn't happening, or —"<</speech>>
<<speech "Aria">>"Thursday is happening."<</speech>>
<<speech "Violet">>"Thursday is at your house and I still haven't been told what to bring."<</speech>>
<<speech "Aria">>"Bring nothing. You brought nothing last time and you'll bring nothing this time."<</speech>>
<<speech "Violet">>"I brought crisps."<</speech>>
<<speech "Aria">>"You brought crisps and then ate them."<</speech>>
<<speech "$name">>"She did do that."<</speech>>
<<speech "Violet">>(mock outrage, jabbing a finger into his shoulder) "Oh, so you're on //her// side."<</speech>>
<<speech "$name">>"She's my girlfriend, Violet."<</speech>>
<<speech "Violet">>"That's a terrible excuse and you know it."<</speech>>
She says it without a flicker of shame, still hanging off him, and slides her arm properly through his while she does — and neither Aria nor Eva reacts, because this is simply what Violet is like.
Violet has had a thing for $name since they were about sixteen and has never made the slightest attempt to hide it. She flirts with him in front of Aria the way she flirts with him everywhere else: loudly, shamelessly, and without any real intent behind it. It is a bit. It has been a bit for three years. Aria finds it funny, mostly, and Violet would be genuinely horrified if anyone thought she meant it as anything else.
<<speech "Violet">>(into his ear, theatrically loud so everyone hears) "You know I asked first, historically."<</speech>>
<<speech "$name">>"You did not ask first. You've never asked at all."<</speech>>
<<speech "Violet">>"I've //implied// constantly."<</speech>>
<<speech "Aria">>(not looking up from her phone) "She has, actually. For years."<</speech>>
<<speech "Violet">>"Thank you, Aria."<</speech>>
<<speech "Aria">>"You're welcome, Violet."<</speech>>
Eva is laughing — and that is the exact moment it happens, with Violet's arm through his and her face six inches away and something in the way she is looking at him that is, underneath the performance, completely serious.
<video src="img/Characters/Violet/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
It is not like the others.
The ones before were //of// somebody — a body, a state of undress, a picture he was shown and could not follow. This is not a picture. This is an act, and it is happening, and he is in it. He cannot say afterwards what he saw because he did not see it from anywhere; there is no camera and no distance, only doing it, only the pressure and the heat and Violet's voice against his ear making a sound he has never heard her make.
Four seconds. Maybe five.
Then the lawn. The bike rack against his hip. Violet's arm still through his, Violet still mid-sentence.
<<speech "Violet">>"— and I'd be a much more attentive girlfriend, is all I'm saying, because I would actually reply to messages —"<</speech>>
<<speech "Eva">>"$name?"<</speech>>
<<speech "$name">>"What?"<</speech>>
<<speech "Eva">>"You've gone the colour of a wall."<</speech>>
<<speech "$name">>"I'm fine."<</speech>>
<<speech "Violet">>(delighted, entirely misreading it) "Oh, have I finally got to you? After all these years?"<</speech>>
<<speech "$name">>"No."<</speech>>
<<speech "Violet">>"You went bright red, you absolutely did."<</speech>>
<<speech "$name">>"Violet, I need you to let go of my arm."<</speech>>
Something in how he says it lands wrong. Violet lets go straight away, and for a fraction of a second the performance drops off her face entirely and she just looks worried, which is somehow worse than anything else that has happened today.
<<speech "Violet">>"…All right. Sorry."<</speech>>
<<speech "$name">>"Don't. It's not you."<</speech>>
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
Eva steps in the way Eva always steps in, which is directly.
<<speech "Eva">>"Right, that's enough. What's going on with you?"<</speech>>
<<speech "$name">>"Nothing's going on with me."<</speech>>
<<speech "Eva">>"You've been like this all day. Marie said you stared at her for five seconds in Chanel's and didn't hear a word."<</speech>>
<<speech "$name">>"Marie exaggerates."<</speech>>
<<speech "Eva">>"Marie has never exaggerated in her life."<</speech>>
She has got hold of his chin before he can stop her, turning his face towards the light to look at his pupils — something she read about once and has been waiting years to use.
<<speech "Eva">>"Both the same. So you're probably not dying."<</speech>>
<<speech "$name">>"Reassuring."<</speech>>
<<speech "Eva">>"I'm serious. You fell over, you hit your head, and now you can't hold a conversation. That's a doctor thing."<</speech>>
She is close enough that he can smell her shampoo, and her hand is warm on his jaw, and it takes him again.
<video src="img/Characters/Eva/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Worse than Violet's, because Violet's had at least started from something Violet was actually doing. This starts from nothing. Eva is holding his face like a paramedic and the thing that arrives is not a version of that, it is not an escalation of that — it is separate and total and utterly unconnected to the woman standing in front of him, and he is doing things to his best friend that he has no framework for having thought about at all.
He hears himself make a noise. Out loud. In the middle of the lawn.
<<speech "Eva">>"Okay. Right. That's it, I'm walking you home."<</speech>>
<<speech "$name">>"No."<</speech>>
<<speech "Eva">>"$name —"<</speech>>
<<speech "$name">>"Eva, I mean it. Please don't touch me for a minute."<</speech>>
She takes her hands off him and steps back, and she does not say anything at all, which from Eva is unheard of.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
And then there is Aria, who has put her phone away.
<<speech "Aria">>"Come here."<</speech>>
<<speech "$name">>"Aria —"<</speech>>
<<speech "Aria">>"I'm not going to interrogate you. Come here."<</speech>>
He goes, because it is Aria and because he has been going when she says that for eight months.
And this time he feels it //coming//.
That is the part he will still be turning over at midnight. There is a gap — a whole second, maybe two — between her putting her arms around him and the thing arriving, and in that gap he can feel it gathering, the way you feel a wave lift under you before it breaks. It is not ambushing him. It is winding up.
Something in him turns towards her and locks on, and he has the distinct, appalling sensation of having been //aimed//.
<video src="img/Characters/Aria/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
It goes on far longer than the others and it is not remotely like being shown something. He is inside it from the first instant with no seam between standing on the lawn and being there, and there is nothing in it he could set down afterwards in any order — only that it is Aria, and that it is relentless, and that some part of him he does not recognise is entirely satisfied by it in a way that has nothing to do with wanting her.
And underneath it, that same flat unbroken note from Saturday night. No louder than it has ever been. But no longer wandering.
//Her.//
When it lets go, his face is in Aria's hair and his hands have closed on her back hard enough that she shifts.
<<speech "Aria">>"Ow. All right."<</speech>>
<<speech "$name">>"Sorry. Sorry."<</speech>>
<<speech "Aria">>(pulling back to look at him, still unworried) "You're shaking."<</speech>>
<<speech "$name">>"I haven't slept since Friday."<</speech>>
<<speech "Aria">>"You're looking at me like it's the first day."<</speech>>
<<speech "$name">>"Maybe I am."<</speech>>
<<speech "Aria">>"Do it more."<</speech>>
She kisses him again, quickly, and tells him to sort his sleep out before Thursday, and goes off across the lawn with Violet, who looks back once.
Eva does not go with them. Eva stands there with her arms folded and watches him for a long moment.
<<speech "Eva">>"I'm not letting this go."<</speech>>
<<speech "$name">>"I know."<</speech>>
<<speech "Eva">>"Tomorrow. I want an actual answer."<</speech>>
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
He walks home the long way, alone, and thinks about it properly for the first time.
Eight. He has counted seven since Saturday night: Kali in the kitchen, three in the dark he can't put in order, four today.
And they have changed. That is what he cannot get around. The ones on Saturday and this morning were pictures of people — shocking, unwanted, over before he understood them. What happened on that lawn was not pictures. He was //doing// things. He was present for them. His body has the memory of it the way it has the memory of a real afternoon.
But it is Aria that he keeps arriving back at.
Every other one has been the same shape: an ambush, out of nowhere, done before he registered it starting. Aria was different in a way he can feel the outline of and cannot name. It knew she was coming. It got ready. It waited until she had her arms around him.
$name has spent two days telling himself a story about a knock on the head, and he has been able to make it fit, more or less, because a knock on the head is a real thing that happens to people.
A knock on the head does not wait for the right girl.
He stops at the corner by the postbox and stands there for a while with that in his hands, turning it over, trying and failing to make it into anything else.
Then he goes home, because it is a Monday, and there is nothing else to do with an afternoon like this one.
<div style="text-align:center; margin-top:32px;">[[Tuesday (1)|Start5]]</div>
</div>
<div class="narrative-box">
Tuesday, and $name wakes up wanting.
Not from a dream. There is no dream to blame it on and nothing to point at — he surfaces out of sleep already at it, hard and hot and aching, and it does not fade while he lies there and it does not fade in the shower and it does not fade over breakfast. It sits in him like a fever that has decided to stay.
By the time he gets to the school gates he has understood that this is simply what today is going to be.
He tries to work with it. He sits at the back. He takes the long way between periods. And it makes no difference at all, because the problem is not the corridor — the problem is that a girl walks past him at the bottom of the stairs, a girl he does not know, and his whole body turns after her like a dog after a car.
That happens perhaps thirty times before lunch.
He eats outside on the wall behind the sports hall where nobody goes, and sits with his elbows on his knees, and thinks: //I am nineteen, I have a girlfriend, and I have never in my life been like this.//
Then Jewelz texts to ask if he can collect Emily from Adriana's class at half three.
And something in him goes //yes// before he has read to the end of the message.
Not a word. A lurch — the way your stomach answers when somebody offers you food and you had not known you were hungry. He is typing //yeah, fine// while the more careful part of him is still assembling reasons, and the reasons all arrive afterwards, and they are all perfectly good ones.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
Adriana's classroom is on the second floor and the lesson runs over, so he waits in the corridor with his shoulder against the wall.
He can hear her through the door. Professor <<charLink "adriana" "Adriana">> has a carrying voice and a way of teaching that involves asking a great many questions. She is not his main professor, but has classes with her often.
The door opens and the class comes out, and Emily is not in the first wave.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Adriana')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Adriana</div></div>
Adriana is, holding the door with her foot and carrying too many folders.
<<speech "Adriana">>"Oh — could you take these two? Just to the top of the stairs."<</speech>>
<<speech "$name">>"Sure."<</speech>>
<<speech "Adriana">>"If you are waiting for Emily, she's on the back packing up."<</speech>>
She holds out the folders, and $name reaches for them, and his hands go underneath hers instead of on top.
He does not decide to do that. There is no thought involved. Something in him simply steers his hands the way you steer a mouthful of food towards your mouth, and his fingers are under hers for a second and a half.
<video src="img/Characters/Adriana/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
He does not drop the folders. He will be proud of that later, in a distant way. And underneath the vision there is a sensation he has no name for and can only think of as //relief// — as though something that had been straining forward for hours has finally got what it wanted, and it is not nearly enough.
<<speech "Adriana">>"Are you all right?"<</speech>>
<<speech "$name">>"Long day."<</speech>>
<<speech "Adriana">>"Mm."<</speech>>
She does not believe him and does not push, which is worse than pushing.
<<speech "Adriana">>"If it's a long week rather than a long day, my door is generally open. Even to people I don't teach."<</speech>>
<<speech "$name">>"I'll remember that."<</speech>>
<<speech "Adriana">>"You won't. But I've said it."<</speech>>
He carries the folders to the top of the stairs and stands there with his heart going, looking at his own hands.
He did that. He put his hands under hers. Nobody made him do anything — there was no voice and no push, only a pull, and the pull came from inside and felt exactly like his own appetite.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Kylie')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Kylie</div></div>
<<charLink "kylie" "Kylie">> comes out three steps behind, sees him, and makes a noise of pure delight.
<<speech "Kylie">>"Cuz! What are you doing up here?"<</speech>>
<<speech "$name">>"Collecting Emily."<</speech>>
<<speech "Kylie">>"You never come up here for meee."<</speech>>
<<speech "$name">>"I've never had a reason to."<</speech>>
She hugs him. Kylie hugs everybody, at full commitment, and she has been doing it to him since she was about four.
And he does not want to let go.
That is all it is. There is no instruction and no plan — just his arms not opening when they should, and a want so simple and so total that it is barely even about her: warm, and close, and //stay//.
$name gets his hands on her shoulders and puts her back from him hard.
It hurts. Not emotionally — physically, low down, a wrench like a cramp, and for two or three seconds afterwards he is angry in a way that has no object at all and does not belong to him.
<video src="img/Characters/Kylie/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
<<speech "Kylie">>"Rude!"<</speech>>
<<speech "$name">>"Sorry. Sorry, Kyl."<</speech>>
<<speech "Kylie">>"Elsa says you fell in a ditch."<</speech>>
<<speech "$name">>"It was a bank. There was no ditch involved at any point."<</speech>>
<<speech "Kylie">>"She said ditch. Are you coming for tea at ours? Lana's doing something with chicken and being weird about it."<</speech>>
<<speech "$name">>"Not tonight."<</speech>>
<<speech "Kylie">>"You always say not tonight."<</speech>>
Emily appears at his elbow with her bag on both shoulders, having materialised the way she does.
<<speech "Emily">>"Ready?"<</speech>>
<<speech "$name">>"God, yes."<</speech>>
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
They walk back through town and Emily does most of the talking, which a year ago would have been remarkable.
$name manages about a third of it. He is walking a careful distance from her shoulder and concentrating on it, and the concentration is taking everything he has.
<<speech "Emily">>"You're not listening."<</speech>>
<<speech "$name">>"I am. Something about the coursework deadline."<</speech>>
<<speech "Emily">>"That was four minutes ago."<</speech>>
<<speech "$name">>"Sorry. I'm somewhere else today."<</speech>>
She walks a little way in silence.
<<speech "Emily">>"You know you can just say. If it's a bad day."<</speech>>
<<speech "$name">>"It's a bad day."<</speech>>
<<speech "Emily">>"All right."<</speech>>
And that's it. She doesn't ask anything else, and being let off the hook that completely makes his chest hurt — and at the same moment, arriving on top of it and not cancelling it out in the slightest, is the pull. Towards her. Warm and stupid and insistent, the same as it was with Kylie on the stairs, no more complicated than a hand reaching for something on a shelf.
$name walks the rest of the way to the corner with his jaw locked, and does not close the gap, and understands somewhere around the postbox that he has spent eleven minutes not touching his own $family and has had to work at it.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
There is a car outside the house, and the car is <<charLink "lana" "Lana">>'s.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Lana')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Lana</div></div>
She is in the kitchen with her feet up on the second chair, still in her work things, eating out of a biscuit tin she found without being told where it was.
<<speech "Lana">>"There he is. The ditch survivor."<</speech>>
<<speech "$name">>"I literally just fell, I'm not injured."<</speech>>
<<speech "Lana">>"That's not what Elsa told Kylie."<</speech>>
<<speech "$name">>"Elsa loves to make up stories and Jewelz is too protective."<</speech>>
Lana works at the museum, which surprises everybody who meets her and nobody who has known her since she was small.
<<speech "Lana">>"Roads were a nightmare coming over. They've shut the whole lane past the research place — police at both ends, two vans, the lot."<</speech>>
<<speech "$name">>"Shut it since when? That's the road I walk on Saturdays."<</speech>>
<<speech "Lana">>"No idea. Somebody at work said there'd been an incident. Somebody else said a spill. I'd guess a burst main and everybody getting excited, because that is what it always is."<</speech>>
<<speech "$name">>"But since when. Saturday? Sunday?"<</speech>>
<<speech "Lana">>"Weekend sometime. Detective <<charLink "angel" "Angel">> is looking at that. Don't quote me. Why, are you writing a piece for the paper?"<</speech>>
<<speech "$name">>"No. I was out that way at the weekend, that's all."<</speech>>
<<speech "Lana">>"Then eat something. You look like a ghost."<</speech>>
She goes back to the tin. The conversation moves on without him and $name stands in his own kitchen holding the edge of the counter.
Saturday. The fence. Half a mile of grey, and a gatehouse, and a car park you can see the corner of.
He puts it away almost at once, because the alternative is a shape he cannot make himself look at, and because Lana is right that it is always a burst main.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Melody')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Melody</div></div>
There are voices in the front room, and he goes towards them.
He is aware, going, that upstairs is the other direction. He goes anyway. He wants to be where the people are and he wants it the way you want water.
It is <<charLink "melody" "Melody">>, cross-legged on the floor with Elsa and sketchbooks between them — Melody has been Elsa's best friend for ten years and is at this house more often than not. She looks up and smiles and says something quiet about the ditch.
And then it happens twice.
<video src="img/Characters/Lana/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
<video src="img/Characters/Melody/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Back to back with no gap at all, the second starting before the first is finished, and this time nobody touched him and nobody was doing anything. He walked into a room where two people were sitting on the floor.
He is holding the doorframe. He has no memory of reaching for it.
<<speech "Elsa">>"$name?"<</speech>>
<<speech "Melody">>"He's gone grey."<</speech>>
<<speech "Elsa">>"$name, sit down —"<</speech>>
<<speech "$name">>"I'm not sitting down. I'm going up and I'm going to lie in the dark for a while."<</speech>>
<<speech "Elsa">>"You are not fine, you look —"<</speech>>
<<speech "$name">>"Elsa, I know exactly how I look. Please just let me go up."<</speech>>
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
He lies on his bed in the dark with the door shut, and it does not stop.
That is the discovery of the evening. It never stops any more. There is no baseline to come back to — the visions come and go and the wanting stays, flat and constant and turned all the way up, and it has been turned all the way up since he opened his eyes this morning.
He tries to think and finds that thinking is now something he has to do //over// the top of it, the way you hold a conversation next to a running engine.
What he manages is this.
It is not making him do things. He has been telling himself since the corridor that something is issuing him instructions, and that is not what it is, and getting it wrong that way has been letting him off. Nobody told him to put his hands under Adriana's. There was no order. He //wanted// to, the way you want to keep hold of something warm, and the wanting was so ordinary and so much his own that he was on the other side of it before he noticed.
It is not a voice in his head. It is an appetite in his body, and it is not his, and it is enormous.
And it is stupid. That is the other thing, and it is nearly the worst. Whatever this is, it does not want anything complicated: it does not care who these people are, it did not care that Elsa is his $family or that Emily is Emily. It wants to be close to somebody. That is all. That is the whole of it. It is exactly as clever as a dog scratching at a door.
He thinks about the doctor's number and the queue.
//I've been having visions// is a sentence. It's mad, but it's a sentence.
//I have been trying not to touch my own $family since three o'clock and it is taking everything I have// is not a thing he can say to a receptionist.
Downstairs the front door goes: Lana leaving, shouting something to Elsa about Thursday, the car pulling off.
$name gets up and packs a bag, because he is going back to the dorm tonight, and there are three people there, and he likes all of them, and none of them is his family.
He is halfway through folding a shirt when he stops, with the shirt in his hands.
Three people. In a small flat.
He stands there for a long moment, understanding perfectly well what he is doing and which part of him thought of it first, and then he finishes folding the shirt and puts it in the bag.
<div style="text-align:center; margin-top:32px;">[[The dorm (1)|Start6]]</div>
</div><<nobr>>
/* ── BASIC SETUP ── */
<<set $weekDay = $daysOfWeek[$day % 7]>>
<<run window.assignDailyLocations()>>
<<set $currentLocation = "House">>
<<set $metToday = false>>
<<set $sceneWatchedToday = false>>
<<set $haremPartyToday = false>>
/* NOTE: $blockedLocations is NOT cleared here. processSuspicionEvents() clears
it and then repopulates it during DayEnd, so wiping it at DayStart deleted
the police patrols before the player ever saw them. */
/* ── FACTION RESET ──
Only the one-day movement hint is cleared here. Clearing _df.directive
wiped every PERSISTENT directive overnight, so Shadow (3d), Cover Story
(3d), Safe House (5d) and Pressure (4d) all expired before their second
day and only ever applied once — their durations were decorative.
processDirectives() already counts daysLeft down and clears them when
they run out. */
<<for _df range $factions>>
<<set _df.directedLocation = null>>
<</for>>
/* ── DAILY ROLLS & BONUSES ── */
<<run window.rollDailyActivities()>>
<<run window.rollDailyScenes()>>
<<if $goalBonuses and $goalBonuses.passiveParasite and $goalBonuses.passiveParasite > 0>>
<<set $parasite += $goalBonuses.passiveParasite>>
<</if>>
/* Goals are rolled at the end of the previous night (processDayEnd STEP 9b)
so the night report can announce them. Rolling again here would consume the
same five-day window silently. */
/* ── LOCATION UNLOCK ── */
<<set _newlyUnlocked = null>>
<<set _locked = $locations.filter(l => !l.unlocked and !l.harem)>>
<<set _baseChance = $day >= 20 ? 95 : $day >= 10 ? 70 : 40>>
<<set _unlockChance = $upgrades && $upgrades.locationDiscovery ? Math.min(100, _baseChance + 20) : _baseChance>>
<<if _locked.length > 0 and random(1, 100) <= _unlockChance>>
<<set _pick = _locked[Math.floor(Math.random() * _locked.length)]>>
<<set _pick.unlocked = true>>
<<set _newlyUnlocked = _pick.navLabel>>
<</if>>
/* ── MORNING VIDEO SCENE LOGIC ── */
<<set _eligibleNames = $roster.filter(name => {
var c = State.variables[name];
/* Captives are held in the mansion — they don't come to greet you, and
they already have their own block further down this passage. */
return c && c.corr >= 25 && !c.arrested && !c.captive;
})>>
<<set _showScene = (_eligibleNames.length > 0 and random(1, 100) <= 75)>>
<<if _showScene>>
<<set _charName = _eligibleNames[Math.floor(Math.random() * _eligibleNames.length)]>>
<<set _mChar = State.variables[_charName]>>
<<set _mName = _mChar.name>>
<<set _mPath = "img/Characters/" + window.getCharFolderName(_mName)>>
<</if>>
/* ── CANCEL PARTIES IF SUSPICION TOO HIGH ── */
<<if $suspicion >= 50>>
<<set $pendingParties = []>>
<<set $pendingClash = null>>
<</if>>
/* ── EVENT INVITES ── */
<div id="event-invite-container">
<<if $pendingClash !== null>>
<<set _f1 = $factions.find(f => f.id === $pendingClash.id1)>>
<<set _f2 = $factions.find(f => f.id === $pendingClash.id2)>>
<<if _f1 and _f2>>
<div style="background:#2a1a00; border:2px solid #ffcc00; border-radius:8px; padding:15px; margin:15px 0;">
<h3 style="color:#ffcc00; margin:0 0 10px 0;">⚡ Faction Clash</h3>
<p><strong><<print _f1.name>></strong> and <strong><<print _f2.name>></strong> are clashing.</p>
<<button "Attend Clash">>
<<set $attendingClash = $pendingClash>>
<<set $pendingClash = null>>
<<goto "FactionClash">>
<</button>>
<<button "Skip">>
<<set $pendingClash = null>>
<<replace "#event-invite-container">><div style="color:#666;">You ignored the conflict.</div><</replace>>
<</button>>
</div>
<</if>>
<</if>>
<<if $pendingParties and $pendingParties.length > 0>>
/* Skip All — one button rather than one click per invitation. Only shown
when there is more than one to skip, and it counts the invitations you
can actually see: a faction whose leader you have not met is dropped
silently further down and never draws a card. */
<<set _visibleParties = $pendingParties.filter(function(pid) {
var pf = $factions.find(f => f.id === pid);
if (!pf) return false;
var pl = State.variables[pf.leader];
return !!(pl && pl.met);
})>>
<<if _visibleParties.length > 1>>
<div id="party-skip-all" style="text-align:right; margin:12px 0 0;">
<<button "Skip all parties">>
<<set $pendingParties = []>>
<<run $(".party-invite-card").hide()>>
<<run $("#party-skip-all").html('<div style="color:#666; font-size:0.88em; padding:4px 0;">You skipped ' + _visibleParties.length + ' party invitations.</div>')>>
<</button>>
</div>
<</if>>
<<for _partyId range $pendingParties>><<capture _partyId>>
<<set _partyFaction = $factions.find(f => f.id === _partyId)>>
<<if _partyFaction>>
<<set _pLeader = State.variables[_partyFaction.leader]>>
<<if _pLeader and _pLeader.met>>
<div @id="'party-invite-' + _partyId" class="party-invite-card" style="background:#1a0020; border:2px solid #bd59ff; border-radius:8px; padding:14px; margin:12px 0;">
<h3 style="color:#bd59ff; margin:0 0 8px 0;">🎉 Party Invitation</h3>
<div style="display:flex; align-items:center; gap:12px; margin-bottom:10px;">
<img @src="window.getPortraitPath(_pLeader.name)" style="width:56px; height:84px; border-radius:6px; border:2px solid #bd59ff; object-fit:cover; object-position:top;">
<p style="margin:0; color:#ccc; font-size:0.9em;"><strong><<print _partyFaction.name>></strong> is throwing a party.</p>
</div>
<<button "Attend Party">>
<<set $attendingParty = _partyId>>
<<set $pendingParties = $pendingParties.filter(id => id !== _partyId)>>
<<goto "FactionParty">>
<</button>>
<<button "Skip">>
<<set $pendingParties = $pendingParties.filter(id => id !== _partyId)>>
<<run $("#party-invite-" + _partyId).html('<div style="color:#666; padding:4px 0;">You skipped the ' + _partyFaction.name + ' party.</div>')>>
<</button>>
</div>
<<else>>
<<set $pendingParties = $pendingParties.filter(id => id !== _partyId)>>
<</if>>
<</if>>
<</capture>><</for>>
<</if>>
</div>
/* ── CAPTIVE INTRODUCTIONS ── */
<<if $pendingCaptiveIntro and $pendingCaptiveIntro.length > 0>>
<div id="captive-intro-block" style="background:#0d0010; border:2px solid #ff4444; border-radius:8px; padding:14px; margin:12px 0;">
<h3 style="color:#ff4444; margin:0 0 10px 0;">🔒 New Captives</h3>
<p style="color:#ccc; font-size:0.9em; margin-bottom:12px;">Your dominated faction has taken prisoners. They are now held under your influence.</p>
<div style="display:flex; flex-wrap:wrap; gap:10px; margin-bottom:12px; justify-content:center;">
<<for _cid range $pendingCaptiveIntro>>
<<set _cc = State.variables[_cid]>>
<<if _cc>>
<<capture _cid>>
<div style="text-align:center; width:130px;">
<img @src="window.getEventImagePath(_cc.name)" style="width:100%; border-radius:6px; border:2px solid #ff4444;">
<div style="color:#ff8888; font-size:0.85em; margin-top:4px; font-weight:bold;"><<print _cc.name>></div>
<div style="color:#666; font-size:0.72em; margin-top:2px;">Held <<print _cc.captiveDays>> day<<if _cc.captiveDays !== 1>>s<</if>> · Corr <<print _cc.corr>>%</div>
</div>
<</capture>>
<</if>>
<</for>>
</div>
<p style="color:#777; font-size:0.82em; font-style:italic; margin:0 0 10px 0; text-align:center;">
They are kept close. You will see more of them tonight.
</p>
<<button "Acknowledged">>
<<set $pendingCaptiveIntro = []>>
<<run $("#captive-intro-block").slideUp()>>
<</button>>
</div>
<</if>>
/* ── ENTHRALLED AGENTS: ABDUCTION APPROVAL ── */
<<if $pendingAbductions and $pendingAbductions.length > 0>>
<div id="abduction-block" style="background:#12000c; border:2px solid #ff8844; border-radius:8px; padding:14px; margin:12px 0;">
<h3 style="color:#ff8844; margin:0 0 6px 0;">🕷 Enthralled Agents</h3>
<p style="color:#ccc; font-size:0.9em; margin:0 0 4px 0;">
Your agents moved in the night. Each one has someone cornered and is waiting on you.
</p>
<p style="color:#ff8866; font-size:0.82em; margin:0 0 12px 0;">
Taking her infects her and holds her captive for 5 days. Each night held she gains <b>infection power + parasite level</b> corruption, ignoring her normal cap. Each abduction costs <b>+10 suspicion</b>.
</p>
<<for _ai, _ab range $pendingAbductions>>
<<capture _ai _ab>>
<<set _agC = State.variables[_ab.agentId]>>
<<set _tgC = State.variables[_ab.targetId]>>
<<if _agC and _tgC>>
<div @id="'abduction-row-' + _ai" style="display:flex; align-items:center; gap:10px; background:#0d0d0d; border:1px solid #2a1a1a; border-radius:6px; padding:8px; margin-bottom:6px;">
<img @src="window.getPortraitPath(_agC.name)" style="width:44px; height:66px; border-radius:5px; object-fit:cover; object-position:top; border:1px solid #ff8844;">
<span style="color:#ff8844; font-size:1.1em;">→</span>
<img @src="window.getPortraitPath(_tgC.name)" style="width:44px; height:66px; border-radius:5px; object-fit:cover; object-position:top; border:1px solid #9c27b0;">
<div style="flex:1; min-width:0; font-size:0.86em; color:#ccc;">
<b style="color:#ff8844;"><<print _agC.name>></b> has
<b style="color:#cc88ff;"><<print _tgC.met ? _tgC.name : "someone">></b>
at <b><<print _ab.location>></b>.
</div>
<span class="loc-btn-wrapper"><<button "Take her">>
<<set _res = window.acceptAbduction(_ai)>>
<<set $pendingAbductions[_ai].done = true>>
<<replace "#abduction-msg">>
<span style="color:#ff8844;">🔒 <<print _res.target>> was taken at <<print _res.location>>. +10 suspicion.</span>
<</replace>>
<<run $("#abduction-row-" + _ai).slideUp()>>
<</button>></span>
<span class="loc-btn-wrapper"><<button "Leave her">>
<<run $("#abduction-row-" + _ai).slideUp()>>
<</button>></span>
</div>
<</if>>
<</capture>>
<</for>>
<div id="abduction-msg" style="font-size:0.85em; margin:8px 0; min-height:1.2em;"></div>
<<button "Done">>
<<set $pendingAbductions = []>>
<<run $("#abduction-block").slideUp()>>
<</button>>
</div>
<</if>>
/* ── ENTHRALL CLASH CHOICE ── */
<<if $pendingClash and $pendingClash.type is "enthrall">>
<<set _clashWinner = $factions.find(f => f.id === $pendingClash.winnerId)>>
<<set _clashLoser = $factions.find(f => f.id === $pendingClash.loserId)>>
<<if _clashWinner and _clashLoser>>
<div id="clash-choice-block" style="background:#1a1000; border:2px solid #ffcc00; border-radius:8px; padding:14px; margin:12px 0;">
<h3 style="color:#ffcc00; margin:0 0 8px 0;">⚡ Clash Aftermath</h3>
<p style="color:#ccc; font-size:0.9em; margin-bottom:10px;">
<b style="color:#ffdd88;"><<print _clashWinner.name>></b> defeated <b style="color:#aaa;"><<print _clashLoser.name>></b>.
What do you do with the losing faction?
</p>
<<button "Dismantle them">>
/* Dismantle loser — leader becomes captive for 10 days */
<<set _losFac = $factions.find(f => f.id === $pendingClash.loserId)>>
<<set _losLeadId = _losFac ? _losFac.leader : null>>
<<set _losLeader = _losLeadId ? State.variables[_losLeadId] : null>>
/* Only a girl you have met can be held. makeCaptive returns false for
a stranger, so don't queue her into the captive intro block either. */
<<if _losLeader and _losLeader.met>>
<<if window.makeCaptive(_losLeadId, 10)>>
<<if !$pendingCaptiveIntro>><<set $pendingCaptiveIntro = []>><</if>>
<<run $pendingCaptiveIntro.push(_losLeadId)>>
<</if>>
<</if>>
<<set _domLoc = $factions.find(f => f.id === $pendingClash.loserId) ? $factions.find(f => f.id === $pendingClash.loserId).homeLocation : null>>
<<if _domLoc and $goalBonuses and $goalBonuses.corruptedLocations>>
<<if !$goalBonuses.corruptedLocations.includes(_domLoc)>>
<<run $goalBonuses.corruptedLocations.push(_domLoc)>>
<</if>>
<</if>>
<<set $factions = $factions.filter(f => f.id !== $pendingClash.loserId)>>
<<set $pendingClash = null>>
<<run $("#clash-choice-block").slideUp()>>
<</button>>
<<button "Let them regroup">>
<<set $pendingClash = null>>
<<run $("#clash-choice-block").slideUp()>>
<</button>>
</div>
<</if>>
<</if>>
/* ── GREETING ── */
<div style="margin:16px 0 8px;">
<div style="font-size:0.75em; text-transform:uppercase; letter-spacing:0.12em; color:#555; margin-bottom:2px;">Day <<print $day>></div>
<div style="font-size:1.3em; color:#ccc;">Good morning, <strong style="color:#bd59ff;">$name</strong>.</div>
<div style="color:#555; font-size:0.88em; margin-top:2px;">$weekDay</div>
</div>
<<if _newlyUnlocked>>
<div style="background:#001a00; border:1px solid #44ff88; border-radius:6px; padding:10px 14px; margin:12px 0;">
<span style="color:#44ff88; font-weight:bold;">📍 New location accessible:</span> <<print _newlyUnlocked>>
</div>
<</if>>
/* ── FIRST MORNING ──
$day starts at 0 in StoryInit and is only incremented by processDayEnd, so
day 0 is the morning straight out of the prologue and nowhere else. No new
variable needed and nothing to reset. */
<<if $day is 0>>
<div style="background:#0d0018; border:1px solid #6a0dad; border-radius:8px; padding:16px 18px; margin:16px 0;">
<div style="color:#bd59ff; font-weight:bold; font-size:1.05em; margin-bottom:6px;">☣ Before you begin</div>
<div style="color:#bbb; font-size:0.92em; line-height:1.65; margin-bottom:12px;">
The game runs on a daily loop: travel, act, sleep, read the night report. Three things in the side menu are worth two minutes now rather than an hour from now.
</div>
<div style="display:flex; flex-direction:column; gap:8px;">
<div style="display:flex; gap:10px; align-items:flex-start;">
<span style="color:#bd59ff; font-weight:bold; min-width:82px;">Tutorial</span>
<span style="color:#999; font-size:0.9em;">How corruption, nests, suspicion and factions actually work. Every number in it is read from the game's own code.</span>
</div>
<div style="display:flex; gap:10px; align-items:flex-start;">
<span style="color:#bd59ff; font-weight:bold; min-width:82px;">Settings</span>
<span style="color:#999; font-size:0.9em;">How many girls appear per scene, which corruption tiers are shown in videos, and how large factions may grow.</span>
</div>
<div style="display:flex; gap:10px; align-items:flex-start;">
<span style="color:#bd59ff; font-weight:bold; min-width:82px;">Shortcuts</span>
<span style="color:#999; font-size:0.9em;">The whole game is playable from the keyboard. <b style="color:#aa8899;">Q</b> advances — it clicks Continue through a scene as well as Sleep and Wake Up. <b style="color:#aa8899;">1</b>–<b style="color:#aa8899;">9</b> pick a girl, <b style="color:#aa8899;">+</b> and <b style="color:#aa8899;">−</b> step forward and back through history, <b style="color:#aa8899;">?</b> opens the list.</span>
</div>
</div>
<div style="text-align:center; color:#777; font-size:0.82em; font-style:italic; margin-top:14px;">
All three are in the side menu on the left, and stay there — you can read them whenever you like.
</div>
</div>
<</if>>
/* ── MORNING VIDEO SCENE ── */
<<if _showScene>>
<div style="background:#000; border:1px solid #333; border-radius:8px; padding:16px; margin:16px 0; text-align:center;">
<h2 style="color:#bd59ff; margin:0 0 14px 0;"><<print _mName>> greets her Master</h2>
<<if _mChar.corr >= 75>>
<<set _s = random(1, 4)>>
<<set _cp = random(1, 2)>>
<video @src="_mPath + '/3/Sex' + _s + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%;"></video>
<video @src="_mPath + '/3/Creampie' + _cp + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%; margin-top:8px;"></video>
<<if !_mChar.breed>>
<<set _mChar.breed = true>>
<h3 style="color:#ff5959; margin-top:12px;">You have bred <<print _mName>>!</h3>
<<else>>
<<set $parasite += 2>>
<h3 style="color:#bd59ff; margin-top:12px;">A new parasite was born from <<print _mName>>! (+2)</h3>
<</if>>
<<elseif _mChar.corr >= 50>>
<<set _b = random(1, 4)>>
<<set _c = random(1, 3)>>
<video @src="_mPath + '/2/BJ' + _b + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%;"></video>
<video @src="_mPath + '/2/Cum' + _c + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%; margin-top:8px;"></video>
<<else>>
<<set _m = random(1, 3)>>
<<set _h = random(1, 3)>>
<video @src="_mPath + '/1/Mast' + _m + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%;"></video>
<video @src="_mPath + '/1/HJ' + _h + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%; margin-top:8px;"></video>
<</if>>
</div>
<hr style="border-color:#333; margin:16px 0;">
<</if>>
/* ── CAPTIVE POOL VIDEOS ── */
<<set _captivePool = $roster.filter(id => State.variables[id] && State.variables[id].captive && !State.variables[id].arrested)>>
<<if _captivePool.length > 0>>
<<set _capPick = _captivePool.random()>>
<<set _capC = State.variables[_capPick]>>
<<set _capPath = "img/Characters/" + window.getCharFolderName(_capC.name)>>
<div style="background:#0a0000; border:1px solid #5a1a1a; border-radius:8px; padding:16px; margin:16px 0; text-align:center;">
<h2 style="color:#ff4444; margin:0 0 4px 0;">🔒 <<print _capC.name>></h2>
<div style="color:#777; font-size:0.8em; margin-bottom:14px; font-style:italic;">
Held captive · <<print _capC.captiveDays>> day<<if _capC.captiveDays !== 1>>s<</if>> remaining · Corr <<print _capC.corr>>%
</div>
<<if _capC.corr >= 75>>
<<set _cs = random(1, 4)>>
<<set _ccp = random(1, 2)>>
<video @src="_capPath + '/3/Sex' + _cs + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%;"></video>
<video @src="_capPath + '/3/Creampie' + _ccp + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%; margin-top:8px;"></video>
/* Captives at 75+ breed exactly as the morning greeter does. She is
held in the mansion every night, so there was no reason she was the
one girl at full corruption who could not be bred — the scene was
already playing, it just did nothing. */
<<if !_capC.breed>>
<<set _capC.breed = true>>
<h3 style="color:#ff5959; margin-top:12px;">You have bred <<print _capC.name>>!</h3>
<<else>>
<<set $parasite += 2>>
<h3 style="color:#bd59ff; margin-top:12px;">A new parasite was born from <<print _capC.name>>! (+2)</h3>
<</if>>
<<elseif _capC.corr >= 50>>
<<set _cb = random(1, 4)>>
<<set _cu = random(1, 3)>>
<video @src="_capPath + '/2/BJ' + _cb + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%;"></video>
<video @src="_capPath + '/2/Cum' + _cu + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%; margin-top:8px;"></video>
<<else>>
<<set _cm = random(1, 3)>>
<<set _ch = random(1, 3)>>
<video @src="_capPath + '/1/Mast' + _cm + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%;"></video>
<video @src="_capPath + '/1/HJ' + _ch + '.mp4'" width="720" autoplay controls loop muted style="border-radius:6px; max-width:100%; margin-top:8px;"></video>
<</if>>
<<if _captivePool.length > 1>>
<div style="color:#555; font-size:0.75em; margin-top:10px;">
<<print _captivePool.length - 1>> other captive<<if _captivePool.length - 1 !== 1>>s<</if>> held.
</div>
<</if>>
</div>
<hr style="border-color:#333; margin:16px 0;">
<</if>>
<<button "Wake Up">><<goto "TownHub">><</button>>
<</nobr>><<nobr>>
<<script>>
window.hasMeetableChar = function(locName) {
var sv = State.variables;
var roster = sv.roster;
if (sv.metToday) return false;
/* Group meetings first, and WITHOUT the co-location test below.
LocationRenderer offers the introduction whenever anyone in the pair is
unmet, wherever the roamer happened to send them — so requiring the girl
to be standing here put the marker back out of step with the button the
moment either of them wandered off. A group pair belongs to its
location; that is the whole point of it. */
var gmsAll = sv.groupMeetings || [];
for (var gj = 0; gj < gmsAll.length; gj++) {
if (gmsAll[gj].location !== locName) continue;
var anyUnmet = gmsAll[gj].members.some(function(mid) {
var mc = sv[mid];
return mc && !mc.met && !mc.arrested;
});
if (anyUnmet) return true;
}
return roster.some(function(id) {
var c = sv[id];
if (!c || c.met || c.arrested) return false;
if (c.location !== locName) return false;
/* Solo: always approachable */
if (c.meetingMethod === "solo") return true;
/* Contact: must match LocationRenderer exactly, or the nav marker and
the actual approach button disagree.
This used to demand a met, corr-25+ connection PHYSICALLY PRESENT at
the location, and to read c.connections directly. LocationRenderer
does neither — it calls getContactIntroducer(), which drops the
co-location requirement and also pools a duo partner's connections.
Result: a contact girl was approachable on the location screen but
never flagged in the map list, so you had to already know to go and
look. Same two helpers now drive both. */
if (c.meetingMethod === "contact") {
if (!window.getContactIntroducer(id)) return false;
var duoLoc = window.getContactLocation(id);
return !duoLoc || duoLoc === locName;
}
/* Group is handled above, before the co-location test. */
return false;
});
};
window.hasLocationScene = function(locName) {
var sv = State.variables;
if (sv.sceneWatchedToday) return false;
var entry = sv.availableScenes && sv.availableScenes[locName];
return !!(entry && (entry.type === "location" || entry.type === "suspicion"));
};
<</script>>
/* ── CLEAR STALE PARTIES ── */
<<if $pendingParties and $pendingParties.length > 0>>
<<if $pendingPartiesDay and $day > $pendingPartiesDay>>
<<set $pendingParties = []>>
<</if>>
<</if>>
<div class="hub-container">
<div class="hub-nav">
<div class="nav-title">Map ($weekDay)</div>
<<if $suspicion >= 25>>
<div style="background:#1a0a00; border:1px solid #ff8844; border-radius:4px; padding:6px 8px; margin:4px 8px; font-size:0.78em;">
<<if $suspicion >= 75>>
<span style="color:#ff2222; font-weight:bold;">⛔ PUBLIC ACCESS DENIED</span>
<<elseif $suspicion >= 50>>
<span style="color:#ff8800; font-weight:bold;">⚠ LIMITED MOVEMENT</span>
<<else>>
<span style="color:#ffcc00;">🔍 Under Surveillance</span>
<</if>>
</div>
<</if>>
/* ── SECTION TOTALS ──
Every undiscovered place used to draw its own "??? (locked)" row,
which told the player nothing except how much they had not found —
and on the School section that was twelve identical lines. The
count is gathered per section up front and shown on the header
instead, and the locked rows are not drawn at all.
The counter disappears once a section is complete, so a finished
map reads as plain headers with no bookkeeping left on it.
The harem is left out of both totals: it is hidden until it
exists, so counting it would give away that it is coming. */
<<set _secTotal to {}>>
<<set _secOpen to {}>>
<<for _lc range $locations>>
<<if _lc.harem>><<continue>><</if>>
<<set _secTotal[_lc.section] to (_secTotal[_lc.section] || 0) + 1>>
<<if _lc.unlocked>>
<<set _secOpen[_lc.section] to (_secOpen[_lc.section] || 0) + 1>>
<</if>>
<</for>>
<<set _lastSection to "">>
<<for _loc range $locations>>
/* The section HEADER is drawn before the per-location checks, so a
hidden location would still print its heading. Skip the whole
entry — header included — for an undiscovered harem. */
<<if _loc.harem and not _loc.unlocked>><<continue>><</if>>
<<if _loc.section isnot _lastSection>>
<<set _sT to _secTotal[_loc.section] || 0>>
<<set _sO to _secOpen[_loc.section] || 0>>
<div class="nav-header"><<print _loc.section>><<if _sT > 0 and _sO < _sT>> <span style="color:#5a4a6a; font-weight:normal; font-size:0.82em;">(<<print _sO>>/<<print _sT>>)</span><</if>></div>
<<set _lastSection to _loc.section>>
<</if>>
/* Locked: draw nothing. The counter on the header above carries
everything the "???" row used to say, in one line instead of
one per location. */
<<if not _loc.unlocked>>
<<continue>>
/* Closed today. LocationData marks the classrooms, hallway,
rooftop, staff room, detention room and student council as
weekdays-only, and the roamer has always honoured that — but
the map never checked it, so you could still walk into an empty
classroom on a Sunday. The Library, Cafeteria, Track and Pool
are weekends:true and stay open, which is correct. */
<<elseif $isWeekend ? not _loc.weekends : not _loc.weekdays>>
<div style="color:#3a3a3a; font-size:0.9em; padding:8px 20px;" @title="_loc.navLabel + ' is closed today.'">
<<print _loc.navLabel>> <span style="font-size:0.8em;">(closed)</span>
</div>
<<elseif $blockedLocations and $blockedLocations.includes(_loc.name)>>
<div style="color:#663333; font-size:0.9em; padding:8px 20px;" @title="'Police are patrolling ' + _loc.name + ' today.'">
<<print _loc.navLabel>> <span style="color:#ff4444;">🚔</span>
</div>
<<elseif not window.canEnterLocation(_loc.name)>>
<div style="color:#444; font-size:0.9em; padding:8px 20px;">
<<print _loc.navLabel>> 🚫
</div>
<<else>>
<<capture _loc>>
<<set _navNest = $nests[_loc.name]>>
<<set _hasActivity = $availableActivities and $availableActivities[_loc.name]>>
<<set _isCorrupted = $goalBonuses and $goalBonuses.corruptedLocations and $goalBonuses.corruptedLocations.includes(_loc.name)>>
<<set _hasMeetable = window.hasMeetableChar(_loc.name)>>
<<set _hasScene = window.hasLocationScene(_loc.name)>>
<<set _actIcon = _hasActivity ? (window.ACTIVITY_DEFS && window.ACTIVITY_DEFS[_loc.name] ? " " + window.ACTIVITY_DEFS[_loc.name].icon : " ◆") : "">>
<<set _nestSuffix = (_navNest && _navNest.level > 0) ? " ☣" + _navNest.level : "">>
<<set _corrSuffix = _isCorrupted ? " ☣" : "">>
<<set _meetSuffix = _hasMeetable ? " ❓" : "">>
<<set _sceneSuffix = _hasScene ? " !" : "">>
<<set _label = _loc.navLabel + _corrSuffix + _nestSuffix + _actIcon + _meetSuffix + _sceneSuffix>>
<<link _label>>
<<set $currentLocation to _loc.name>>
<<replace "#hub-content">><<include "LocationRenderer">><</replace>>
<</link>>
<</capture>>
<</if>>
<</for>>
<div class="nav-footer">
<<link "Sleep (End Day)">><<goto "DayEnd">><</link>>
</div>
</div>
<div id="hub-content" class="hub-display">
<<include "LocationRenderer">>
</div>
</div>
<</nobr>><<nobr>>
/* ── 1. DATA RESOLUTION ── */
<<set _locObj = $locations.find(function(l) { return l.name === $currentLocation; })>>
/* Guard: the mansion is hidden from the map until it is unlocked, but a save
made mid-session could still be sitting on it. Bounce to the House rather
than render a location the player is not supposed to know exists yet. */
<<if _locObj and _locObj.harem and not _locObj.unlocked>>
<<set $currentLocation = "House">>
<<set _locObj = $locations.find(function(l) { return l.name === "House"; })>>
<</if>>
<<set _locTrait = _locObj ? _locObj.trait : "public">>
<<set _locSect = _locObj ? _locObj.section : "">>
<<set _nest = $nests[$currentLocation]>>
<<set _corrCap = window.getCorrCap ? window.getCorrCap() : 25>>
/* ── 2. GROUP MEETING ROLL ── */
<<if $groupMeetingRollLoc !== $currentLocation>>
<<set $groupMeetingRollLoc = $currentLocation>>
<<set $groupMeetingActive = true>>
<</if>>
/* ── 3. HEADER ── */
<div class="loc-header">
<div style="flex:1;">
<<if _locSect>>
<div class="nav-header" style="margin:0 0 6px 0; padding:4px 0;"><center><<print _locSect>></center></div>
<</if>>
<div style="display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;">
<h1 style="margin:0; font-size:2em; text-transform:uppercase;">$currentLocation</h1>
<<if _locTrait === "critical">>
<span style="font-size:0.6em; color:#ff2222; background:#1a0000; border:1px solid #ff2222; border-radius:3px; padding:2px 6px;">CRITICAL</span>
<<elseif _locTrait === "intimate">>
<span style="font-size:0.6em; color:#44ff88; background:#001a0a; border:1px solid #44ff88; border-radius:3px; padding:2px 6px;">PRIVATE</span>
<<else>>
<span style="font-size:0.6em; color:#88aaff; background:#00081a; border:1px solid #88aaff; border-radius:3px; padding:2px 6px;">PUBLIC</span>
<</if>>
<<if $goalBonuses && $goalBonuses.corruptedLocations && $goalBonuses.corruptedLocations.includes($currentLocation)>>
<span style="font-size:0.6em; color:#bd59ff; background:#0d0018; border:1px solid #bd59ff; border-radius:3px; padding:2px 6px;">☣ DOMINATED</span>
<</if>>
</div>
</div>
<div class="parasite-counter">Parasites: <span style="color:#bd59ff; font-weight:bold;">$parasite</span></div>
</div>
/* ── 4. SCENE BLOCK ── */
<<if $sceneWatchedToday is false>>
<<set _sceneEntry = ($availableScenes and $availableScenes[$currentLocation]) ? $availableScenes[$currentLocation] : null>>
<<if _sceneEntry and _sceneEntry.type is "suspicion">>
<div style="background:#1a0500; border:1px solid #ff4444; border-radius:8px; padding:10px 14px; margin-bottom:16px; display:flex; justify-content:space-between; align-items:center;">
<div>
<div style="color:#ff4444; font-weight:bold; font-size:0.88em;">⚠ INVESTIGATION ACTIVE</div>
<div style="color:#666; font-size:0.75em; margin-top:2px;">Authorities are scrutinizing the area.</div>
</div>
<<button "Observe Risk">>
<<set $sceneWatchedToday = true>>
<<set $sceneLocation = $currentLocation>>
<<goto "SuspicionScene-Router">>
<</button>>
</div>
<<elseif _sceneEntry and _sceneEntry.type is "location">>
<div style="background:#0a001a; border:1px solid #9c27b0; border-radius:8px; padding:10px 14px; margin-bottom:16px; display:flex; justify-content:space-between; align-items:center;">
<div>
<div style="color:#bd59ff; font-weight:bold; font-size:0.88em;">🎬 Scene Available</div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Something is happening here today.</div>
</div>
<<button "Watch Scene">>
<<set $sceneWatchedToday = true>>
<<set $sceneLocation = $currentLocation>>
<<goto "LocationScene-Router">>
<</button>>
</div>
<</if>>
<<else>>
<<if _sceneEntry>>
<div style="text-align:center; color:#444; font-size:0.8em; font-style:italic; margin-bottom:16px;">(You have already observed a scene today)</div>
<</if>>
<</if>>
/* ── 5. GROUP INTERACTION ── */
<<set _ready = $roster.filter(function(id) { return State.variables[id].location === $currentLocation && State.variables[id].corr >= 25; })>>
<<if _ready.length >= 2>>
<div style="margin-bottom:16px; padding:10px 12px; background:#111; border:1px solid #9c27b0; text-align:center; border-radius:8px;">
<strong style="color:#bd59ff;">Group Interaction Available</strong>
<div style="margin-top:6px;">
<span class="loc-btn-wrapper" style="max-width:300px; display:inline-block;">
<<button "Spend Time with All">><<goto "GroupInteract">><</button>>
</span>
</div>
</div>
<</if>>
/* ── 6. GROUP MEETING BUTTON ── */
<<set _locGroupPair = $groupMeetings.find(function(g) { return g.location === $currentLocation; })>>
<<if _locGroupPair && $groupMeetingActive>>
<<set _lgAnyUnmet = _locGroupPair.members.some(function(id) { return !State.variables[id].met; })>>
/* The pair used to also have to be standing here today. They live and work
at this location — that is what a group meeting IS — so on any day the
roamer sent them elsewhere the introduction silently disappeared with no
way to tell whether it had ever existed. If somebody in the pair is
still unmet, the meeting is available at their own location, always. */
/* The panel is shown whenever the pair is genuinely approachable, and only
the BUTTON is withheld once you have already met someone today. It used
to hide the whole thing on `!$metToday`, so after your first meeting of
the day the group vanished from the location with no explanation — which
read as the meeting having stopped existing rather than as the one-a-day
rule it actually is. */
<<if _lgAnyUnmet>>
<<set _lgTarget = _locGroupPair.members.find(function(id) { return !State.variables[id].met; })>>
<div style="margin-bottom:16px; padding:10px 12px; background:#0d001a; border:1px solid #7a3a9a; text-align:center; border-radius:8px;">
<strong style="color:#cc88ff;">👥 Group Meeting Available</strong>
<div style="color:#888; font-size:0.85em; margin:4px 0 6px;">Some familiar faces are here.</div>
<<if $metToday>>
<div style="color:#665544; font-size:0.85em; font-style:italic;">You have already introduced yourself to someone today.</div>
<<else>>
<span class="loc-btn-wrapper" style="max-width:300px; display:inline-block;">
<<button "Introduce yourself">>
<<set $meetingTarget = _lgTarget>>
<<goto "MeetingWrapper">>
<</button>>
</span>
<</if>>
</div>
<</if>>
<</if>>
/* ── 7. CLASS LECTURE ── */
<<if $currentLocation.includes("Class") or $currentLocation is "School Pool">>
<<if $weekDay !== "Saturday" && $weekDay !== "Sunday">>
<div style="margin-bottom:16px; text-align:center;">
<span class="loc-btn-wrapper" style="display:inline-block; width:250px;">
<<button "Start Lecture (Event)">><<goto "ClassLecture">><</button>>
</span>
</div>
<<else>>
<div style="text-align:center; color:#555; margin-bottom:16px; font-style:italic;">(Classes are closed on weekends)</div>
<</if>>
<</if>>
/* ── 8. ACTIVITY BUTTON ── */
/* The mansion's party is always on the table — it is never rolled. */
<<if _locObj and _locObj.harem>>
<div style="margin-bottom:16px; text-align:center;">
<<if $haremPartyToday>>
<div style="color:#666; font-style:italic; font-size:0.88em;">
The house is still full of last night. No second party today.
</div>
<<else>>
<span class="loc-btn-wrapper" style="display:inline-block; min-width:250px;">
<<button "🍾 Host a Party">>
<<set $haremGuests = []>>
<<goto "HaremPartyPicker">>
<</button>>
</span>
<div style="color:#555; font-size:0.76em; margin-top:4px;">
Invite anyone you have met — anywhere else you get whoever happens to be there.
</div>
<</if>>
</div>
<<elseif $availableActivities && $availableActivities[$currentLocation]>>
<<set _actDef = window.ACTIVITY_DEFS ? window.ACTIVITY_DEFS[$currentLocation] : null>>
<<set _actLbl = _actDef ? (_actDef.icon + " " + _actDef.name) : $availableActivities[$currentLocation]>>
<div style="margin-bottom:16px; text-align:center;">
<span class="loc-btn-wrapper" style="display:inline-block; min-width:250px;">
<<button _actLbl>><<goto "Activity">><</button>>
</span>
</div>
<</if>>
/* ── 9. CHARACTER GRID ── */
<<set _foundAny = false>>
<<set _girlCardNum = 0>>
<div class="loc-grid">
<<for _id range $roster>>
<<set _char = State.variables[_id]>>
<<if _char.location === $currentLocation>>
<<set _foundAny = true>>
<<capture _id>>
<<if !_char.met>>
<<set _method = _char.meetingMethod>>
<<set _canApproach = false>>
<<set _hint = "">>
<<set _foundIntro = null>>
<<if _method === "solo">>
<<set _canApproach = true>>
<<set _hint = "You haven't spoken to her yet.">>
<<elseif _method === "group">>
<<set _gPair = $groupMeetings.find(function(g) { return g.members.includes(_id); })>>
<<set _partnerHere = false>>
<<if _gPair>>
<<for _pid range _gPair.members>>
<<if _pid !== _id && State.variables[_pid].location === $currentLocation>>
<<set _partnerHere = true>>
<</if>>
<</for>>
<</if>>
<<if _partnerHere>>
<<set _hint = "She's here with someone.">>
<<else>>
<<set _hint = "You'd need to find her in the right company.">>
<</if>>
<<elseif _method === "contact">>
/* The introducer no longer has to be present — knowing her at
corruption 25+ is enough. Duos are met together at their
shared location. */
<<set _foundIntro = window.getContactIntroducer(_id)>>
<<set _duoLoc = window.getContactLocation(_id)>>
<<if _foundIntro>>
<<if _duoLoc and _duoLoc isnot $currentLocation>>
<<set _hint = State.variables[_foundIntro].name + " mentioned her — she's usually at the " + _duoLoc + ".">>
<<else>>
<<set _canApproach = true>>
<<set _hint = State.variables[_foundIntro].name + " has mentioned her.">>
<</if>>
<<else>>
<<set _hint = "You'd need someone to introduce you.">>
<</if>>
<</if>>
<<set _girlCardNum += 1>>
<div class="loc-card" @data-girl-key="_girlCardNum" data-girl-card>
<div class="loc-portrait" style="display:flex; align-items:center; justify-content:center; background:#000;">
<span style="font-size:3em; color:#222;">?</span>
</div>
<div class="loc-info">
<div class="loc-name">???</div>
<<if _hint>>
<div class="unaware-tag"><<print _hint>></div>
<</if>>
<<if _canApproach && !$metToday>>
<<capture _id _foundIntro>>
<span class="loc-btn-wrapper">
<<button "Approach">>
<<set $meetingTarget = _id>>
<<set $meetingIntroducer = _foundIntro>>
<<goto "MeetingWrapper">>
<</button>>
</span>
<</capture>>
<<elseif _canApproach>>
<span style="color:#555; font-size:0.8em; font-style:italic;">Already made an introduction today.</span>
<</if>>
</div>
</div>
<<else>>
<<set _imgSrc = window.getPortraitPath(_char.name)>>
<<set _girlCap = window.getCorrCap ? window.getCorrCap(_id) : _corrCap>>
<<set _atCorrCap = _char.infected && (_char.corr >= _girlCap) && (_char.corr < 100)>>
<<set _canLevelUp = _atCorrCap>>
<<set _hasGirlScene = false>>
<<if window.GIRL_SCENES && window.GIRL_SCENES[_id]>>
<<set _gs = window.GIRL_SCENES[_id]>>
<<if _gs.check && _gs.check()>><<set _hasGirlScene = true>><</if>>
<</if>>
<<set _girlCardNum += 1>>
<div class="loc-card" @data-girl-key="_girlCardNum" data-girl-card>
<div class="loc-portrait" @style="'background-image: url(' + _imgSrc + ')'">
<div class="loc-bar-container">
<div class="loc-bar-fill" @style="'width: ' + _char.corr + '%'"></div>
</div>
<<if _atCorrCap>>
<div style="position:absolute; top:4px; right:4px; background:#bd59ff; color:#fff; font-size:0.6em; font-weight:bold; padding:2px 5px; border-radius:3px;">CAP</div>
<</if>>
</div>
<div class="loc-info">
<div class="loc-name"><<charLink _id>></div>
<div style="font-size:0.72em; color:#555; margin-bottom:4px;">
Corr: <<print _char.corr>>
<<if _atCorrCap>><span style="color:#bd59ff;"> — at cap (<<print _girlCap>>)</span><</if>>
</div>
<div class="loc-actions">
<<if _hasGirlScene>>
<<capture _id>>
<span class="loc-btn-wrapper">
<<button "🎬 Scene">>
<<set $sceneTarget = _id>>
<<set $sceneContext = window.GIRL_SCENES[_id].context || "">>
<<set $sceneReturn = "TownHub">>
<<if window.GIRL_SCENES[_id].onTrigger>><<run window.GIRL_SCENES[_id].onTrigger()>><</if>>
<<goto "GirlScene">>
<</button>>
</span>
<</capture>>
<</if>>
<<if _canLevelUp>>
<<set _lvlNeeded = _girlCap is 25 ? 2 : _girlCap is 50 ? 3 : 4>>
<<if $parasiteLevel >= _lvlNeeded and $parasite >= 1>>
<<capture _id _girlCap>>
<span class="loc-btn-wrapper">
<<button "⬆ Break Cap (1pt)">>
<<set $parasite -= 1>>
<<run window.breakCorrCap(_id)>>
<<set State.variables[_id].corr = Math.min(window.getCorrCap(_id), State.variables[_id].corr + 1)>>
<<set $capBreakTarget = _id>>
<<set $capBreakReturn = "TownHub">>
<<goto "CapBreakScene">>
<</button>>
</span>
<</capture>>
<<elseif $parasiteLevel < _lvlNeeded>>
<div style="color:#555; font-size:0.72em; font-style:italic;">Requires Parasite Level <<print _lvlNeeded>></div>
<<else>>
<div style="color:#555; font-size:0.72em; font-style:italic;">Need 1pt</div>
<</if>>
<</if>>
<<if _char.corr >= 25>>
<<button "Interact">><<set $interactTarget = _id>><<goto "SpendTime">><</button>>
<</if>>
<<if !_char.infected && $parasite >= 1>>
<<set _nestObjHere = $nests[$currentLocation]>>
<<set _nestHere = _nestObjHere && _nestObjHere.level > 0 && (_nestObjHere.type || "spreading") isnot "breeding">>
<<set _breedingHere = _nestObjHere && _nestObjHere.level > 0 && _nestObjHere.type is "breeding">>
<<set _connVec = null>>
<<for _vcid range _char.connections>>
<<set _vc = State.variables[_vcid]>>
<<if _vc && _vc.corr >= 25 && _vc.location === $currentLocation>>
<<if !_connVec>><<set _connVec = _vcid>><</if>>
<</if>>
<</for>>
<div style="display:flex; flex-wrap:wrap; gap:3px; margin-top:4px;">
<<capture _id>>
<span class="loc-btn-wrapper">
<<button "Infect (1pt)">>
<<set $interactTarget = _id>>
<<set $infectMethod = "direct">>
<<goto "InfectScene">>
<</button>>
</span>
<</capture>>
<<if _nestHere and $parasite >= 2>>
<<capture _id>>
<span class="loc-btn-wrapper">
<<button "Expose (2pt)">>
<<set $interactTarget = _id>>
<<set $infectMethod = "exposure">>
<<goto "InfectScene">>
<</button>>
</span>
<</capture>>
<<elseif _nestHere>>
<span style="color:#444; font-size:0.78em; font-style:italic;">Expose (need 2pt)</span>
<<elseif _breedingHere>>
<span style="color:#333; font-size:0.78em; font-style:italic;">Expose (needs spreading nest)</span>
<<else>>
<span style="color:#333; font-size:0.78em; font-style:italic;">Expose (needs nest)</span>
<</if>>
<<if _connVec>>
<<capture _id _connVec>>
<span class="loc-btn-wrapper">
<<button "Vector (1pt)">>
<<set $interactTarget = _id>>
<<set $infectMethod = "vector">>
<<set $infectVectorSrc = _connVec>>
<<goto "InfectScene">>
<</button>>
</span>
<</capture>>
<<else>>
<span style="color:#333; font-size:0.78em; font-style:italic;">Vector (need ally here)</span>
<</if>>
</div>
<</if>>
</div>
</div>
</div>
<</if>>
<</capture>>
<</if>>
<</for>>
</div>
<<if !_foundAny>>
<div class="empty-msg">There is nobody here right now.</div>
<</if>>
/* ── 10. NEST FOOTER ── */
<div class="nest-footer">
<<if _nest>>
<<set _isCorrupted = ($goalBonuses && $goalBonuses.corruptedLocations && $goalBonuses.corruptedLocations.includes($currentLocation))>>
<<set _plantCost = _isCorrupted ? 1 : 2>>
<<set _nestType = _nest.type || "spreading">>
<<set _nestSpec = _nest.specialisation || null>>
<<set _nestCount = Object.keys($nests).filter(function(k) { return $nests[k] && $nests[k].level > 0; }).length>>
<<set _nestAtCap = _nest.level === 0 && _nestCount >= $nestCap>>
<div style="display:flex; justify-content:space-between; align-items:flex-start;">
<div>
<strong>Nest:</strong>
<<if _nest.level > 0>>
<<set _nestLabel = window.getNestLabel(_nest)>>
<span class="corrupt">☣ <<print _nestLabel>> (L<<print _nest.level>>)</span>
<span style="color:#666; font-size:0.85em; margin-left:8px;"><<print _nest.days>> day<<if _nest.days !== 1>>s<</if>> remaining</span>
<div style="color:#888; font-size:0.75em; margin-top:3px; font-style:italic;">
<<if _nestType is "breeding">>☣ Generates +1 parasite each night
<<elseif _nestSpec is "corruption">>☣ Deeply corrupts infected girls here
<<elseif _nestSpec is "spread">>☣ Aggressively spreads the parasite
<<elseif _nestSpec is "stealth">>☣ Hidden network — suspicion suppressed
<<elseif _nest.level >= 3>>
<<if _locTrait is "intimate">>☣ Infecting here draws less attention
<<elseif _locTrait is "academic">>☣ Anchored girls corrupt faster
<<elseif _locTrait is "socialHub">>☣ Corruption seeps to nearby girls
<<elseif _locTrait is "outdoor">>☣ Infected are drawn to this place
<<elseif _locTrait is "transient">>☣ Passing girls are being seeded
<</if>>
<</if>>
</div>
<<if _nestSpec isnot "stealth" and _nest.level > 3 and _locTrait isnot "intimate">>
<div style="color:#ff8844; font-size:0.75em; margin-top:2px;">
⚠ Detection risk: <<print Math.round((window.NEST_DETECT_BASE ? window.NEST_DETECT_BASE[_nest.level] : 0.10) * 100)>>% base
</div>
<</if>>
<<else>>
<span style="color:#aaa;">None</span>
<<if _nestAtCap>>
<span style="color:#ff5555; font-size:0.8em; margin-left:8px;">⚠ Nest cap reached (<<print _nestCount>>/<<print $nestCap>>)</span>
<</if>>
<</if>>
</div>
<div style="text-align:right;">
<<if _locTrait is "critical" and !window.hasUpgrade("nestCritical")>>
<span style="color:#444; font-size:0.8em;">Nests not permitted here</span>
<<elseif _nestAtCap>>
<span style="color:#555; font-size:0.8em;">Nest cap full (<<print _nestCount>>/<<print $nestCap>>)</span>
<<elseif _nest.level === 0>>
<<if $parasite >= 1>>
<div style="display:flex; flex-direction:column; gap:4px; align-items:flex-end;">
<<if $parasite >= _plantCost>>
<<set _spreadLbl = "Plant Spreading Nest (" + _plantCost + "pt)">>
<span class="loc-btn-wrapper">
<<button _spreadLbl>>
<<run window.plantNest($currentLocation, "spreading")>>
<<run $("#hub-content").empty().wiki(Story.get("LocationRenderer").processText()); UI.update();>>
<</button>>
</span>
<<else>>
<span style="color:#555; font-size:0.78em;">Spreading nest needs <<print _plantCost>>pt</span>
<</if>>
<span class="loc-btn-wrapper">
<<button "Plant Breeding Nest (1pt)">>
<<run window.plantNest($currentLocation, "breeding")>>
<<run $("#hub-content").empty().wiki(Story.get("LocationRenderer").processText()); UI.update();>>
<</button>>
</span>
<div style="font-size:0.72em; color:#555; margin-top:2px;">Breeding: +1 parasite/night</div>
</div>
<<else>>
<span style="color:#555; font-size:0.8em;">Need 1pt to plant</span>
<</if>>
<<elseif _nestType is "breeding">>
<<if $parasite >= 1>>
<span class="loc-btn-wrapper">
<<button "Nourish (+2 days, 1pt)">>
<<run $nests[$currentLocation].days += 2>>
<<run $parasite -= 1>>
<<run $("#hub-content").empty().wiki(Story.get("LocationRenderer").processText()); UI.update();>>
<</button>>
</span>
<<else>>
<span style="color:#555; font-size:0.8em; font-style:italic;">Need 1pt to nourish</span>
<</if>>
<<elseif _nest.level is 2 and !_nestSpec>>
<<set _specCost = 10>>
<div style="display:flex; flex-direction:column; gap:4px; align-items:flex-end;">
<div style="font-size:0.78em; color:#cc88ff; margin-bottom:4px;">Choose specialisation (L3, <<print _specCost>>pt):</div>
<<if $parasite >= _specCost>>
<span class="loc-btn-wrapper">
<<button "☣ Corruption">>
<<run window.specialiseNest($currentLocation, "corruption")>>
<<run $("#hub-content").empty().wiki(Story.get("LocationRenderer").processText()); UI.update();>>
<</button>>
</span>
<span class="loc-btn-wrapper">
<<button "☣ Spread">>
<<run window.specialiseNest($currentLocation, "spread")>>
<<run $("#hub-content").empty().wiki(Story.get("LocationRenderer").processText()); UI.update();>>
<</button>>
</span>
<span class="loc-btn-wrapper">
<<button "☣ Stealth">>
<<run window.specialiseNest($currentLocation, "stealth")>>
<<run $("#hub-content").empty().wiki(Story.get("LocationRenderer").processText()); UI.update();>>
<</button>>
</span>
<<else>>
<span style="color:#555; font-size:0.8em;">Need <<print _specCost>>pt to specialise</span>
<</if>>
</div>
<<elseif _nest.level < 5>>
<<set _upCosts = [0, 3, 6, 0, 15]>>
<<set _cost = _upCosts[_nest.level] || 15>>
<<set _upgLbl = "Upgrade → " + window.getNestStage(_nest.level + 1) + " (" + _cost + "pt)">>
<<if $parasite >= _cost>>
<span class="loc-btn-wrapper">
<<button _upgLbl>>
<<run window.upgradeNest($currentLocation)>>
<<run $("#hub-content").empty().wiki(Story.get("LocationRenderer").processText()); UI.update();>>
<</button>>
</span>
<<if _nest.level >= 3 and _nestSpec isnot "stealth" and _locTrait isnot "intimate">>
<div style="color:#ff8844; font-size:0.75em; margin-top:3px;">⚠ Upgrade raises suspicion (+10)</div>
<</if>>
<<else>>
<span style="color:#555; font-size:0.8em;">Need <<print _cost>>pt to upgrade</span>
<</if>>
/* ── FREE UPGRADE VIA A BRED GIRL ──
window.upgradeNestWithVector() has existed since the nest system
was written and the Tutorial documents it, but no button ever
called it — so the "free upgrade" was unreachable. Conditions
come straight from the function: spreading nest, level 1/3/4
(never across the level-2 specialisation gate), and a girl who
is HERE, corrupted 75+, and carries the breed flag. */
<<set _vecGirl = null>>
<<if _nestType isnot "breeding" and _nest.level isnot 2>>
<<for _vgid range $roster>>
<<set _vgc = State.variables[_vgid]>>
<<if !_vecGirl and _vgc and _vgc.breed and _vgc.corr >= 75 and _vgc.location is $currentLocation and !_vgc.arrested>>
<<set _vecGirl = _vgid>>
<</if>>
<</for>>
<</if>>
<<if _vecGirl>>
<<capture _vecGirl>>
<<set _vecLbl = "🩸 Feed " + State.variables[_vecGirl].name + " to the nest (free)">>
<span class="loc-btn-wrapper">
<<button _vecLbl>>
<<run window.upgradeNestWithVector($currentLocation, _vecGirl)>>
<<run $("#hub-content").empty().wiki(Story.get("LocationRenderer").processText()); UI.update();>>
<</button>>
</span>
<</capture>>
<div style="color:#7a5a8a; font-size:0.74em; margin-top:2px;">Spends her breeding. No parasites, no suspicion.</div>
<</if>>
<</if>>
</div>
</div>
<<else>>
<span style="color:#aaa;">None</span>
<</if>>
</div>
<</nobr>><<nobr>>
<<set _c = State.variables[$interactTarget]>>
<<set _imgSrc = window.getEventImagePath(_c.name)>>
<<set _corrCap = window.getCorrCap ? window.getCorrCap($interactTarget) : 25>>
<<set _oldStage = window.getCorrSuffix(_c.corr)>>
<<set _ups = $upgrades || {}>>
<<set _tier = "Unaware">>
<<if _c.corr gte 100>><<set _tier = "Vector">>
<<elseif _c.corr gte 75>><<set _tier = "Devoted">>
<<elseif _c.corr gte 50>><<set _tier = "Receptive">>
<<elseif _c.corr gte 25>><<set _tier = "Curious">>
<</if>>
<<set _tierColor = {
"Vector": "#ff4444",
"Devoted": "#ff88cc",
"Receptive": "#bd59ff",
"Curious": "#88aaff",
"Unaware": "#555"
}[_tier]>>
/* ── APPLY PROXIMITY EFFECT UPGRADE ── */
/* corrTickSameLocation: ticks all other infected girls at same location */
<<if _ups.corrTickSameLocation or _ups.corrTickSameLocation2>>
<<set _sameLocTick = _ups.corrTickSameLocation2 ? 2 : 1>>
<<for _pid range $roster>>
<<set _pc = State.variables[_pid]>>
/* Each girl is clamped to HER OWN cap — a girl whose cap has been
broken must not be pulled back down to the global ceiling. */
<<set _pcCap = window.getCorrCap ? window.getCorrCap(_pid) : 25>>
<<if _pid isnot $interactTarget and _pc.infected and _pc.location is _c.location and _pc.corr < _pcCap and !_pc.arrested>>
<<set _pc.corr = Math.min(_pcCap, _pc.corr + _sameLocTick)>>
<</if>>
<</for>>
<</if>>
/* ── CHECK FOR GIRL SCENE ── */
<<set _hasGirlScene = false>>
<<if window.GIRL_SCENES and window.GIRL_SCENES[$interactTarget]>>
<<set _gs = window.GIRL_SCENES[$interactTarget]>>
<<if _gs.check and _gs.check()>>
<<set _hasGirlScene = true>>
<</if>>
<</if>>
<</nobr>>
/* ── HEADER ── */
<div style="text-align:center; margin-bottom:16px;">
<img @src="_imgSrc" style="max-width:320px; width:80%; border-radius:10px; border:2px solid <<print _tierColor>>; display:block; margin:0 auto 10px;">
<h1 style="margin:0; color:<<print _tierColor>>;"><<print _c.name>></h1>
<div style="color:#555; font-size:0.85em; margin-top:4px;">
<<print _tier>> · Corr: <<print _c.corr>>
<<if _c.corr >= _corrCap and _c.corr < 100>>
<span style="color:#bd59ff;"> — at cap (<<print _corrCap>>)</span>
<</if>>
</div>
</div>
/* ── VIDEO SECTION ── */
<div style="background:#000; padding:12px; border:1px solid #333; border-radius:8px; margin-bottom:16px;">
<<CharacterVideos $interactTarget>>
</div>
/* ── NARRATIVE ── */
<div style="font-style:italic; color:#aaa; margin-bottom:16px; text-align:center; padding:10px 16px; background:#111; border-radius:6px; font-size:0.9em; line-height:1.7;">
<<if _tier is "Curious">>
She is getting used to your presence. She allows you to watch and touch, but is still hesitant.
<<elseif _tier is "Receptive">>
She craves the parasite's influence. She eagerly performs for you, her inhibitions melting away.
<<elseif _tier is "Devoted" or _tier is "Vector">>
She belongs to you completely. There is nothing she won't do to please her master.
<<else>>
She doesn't suspect a thing yet. You spend the time talking, planting subtle seeds in her mind.
<</if>>
</div>
/* ── BREEDING MECHANIC ── */
<<if _c.corr gte 75 and !_c.breed>>
<div style="background:#1a0000; border:2px solid #ff4444; padding:12px; margin-bottom:16px; text-align:center; border-radius:6px;">
<strong style="color:#ff8888;">BREEDING TRIGGERED</strong><br>
<span style="color:#aaa; font-size:0.88em;">She will produce a parasite offspring tonight.</span>
<<set _c.breed = true>>
</div>
<</if>>
/* ── GIRL SCENE BUTTON ── */
<<if _hasGirlScene>>
<div style="text-align:center; margin-bottom:16px;">
<<button "🎬 Scene">>
<<set $sceneTarget = $interactTarget>>
<<set $sceneContext = window.GIRL_SCENES[$interactTarget].context || "">>
<<set $sceneReturn = "SpendTime">>
<<if window.GIRL_SCENES[$interactTarget].onTrigger>><<run window.GIRL_SCENES[$interactTarget].onTrigger()>><</if>>
<<goto "GirlScene">>
<</button>>
</div>
<</if>>
/* ── CHECK LEVEL UP (stage crossed during this visit) ── */
<<nobr>>
<<set _newStage = window.getCorrSuffix(_c.corr)>>
<<if _newStage isnot _oldStage and _newStage isnot "Normal">>
<<set $levelUpTarget = $interactTarget>>
<<set $levelUpStage = _newStage>>
<<set $levelUpReturn = "TownHub">>
<</if>>
<</nobr>>
/* ── EXIT BUTTONS ── */
<div style="text-align:center; margin-top:20px; display:flex; gap:12px; justify-content:center; flex-wrap:wrap;">
<<button "Return to Town">>
<<set $interactTarget = null>>
<<if $levelUpTarget>>
<<goto "CorrLevelUp">>
<<else>>
<<goto "TownHub">>
<</if>>
<</button>>
<<button "Sleep">>
<<set $interactTarget = null>>
<<if $levelUpTarget>>
<<set $levelUpReturn = "DayEnd">>
<<goto "CorrLevelUp">>
<<else>>
<<goto "DayEnd">>
<</if>>
<</button>>
</div><<run window.processDayEnd()>>
<<if $gameOver>>
<div style="background:#1a0000; border:3px solid #ff0000; padding:30px; margin:20px 0; text-align:center; border-radius:8px;">
<h1 style="color:#ff0000; font-size:2.5em; text-shadow:0 0 20px #ff0000;">☠ OPERATION COMPROMISED</h1>
<p style="color:#ff8888; font-size:1.2em;">
Your activities have been fully exposed. Authorities have dismantled the infection network.<br>
$name is taken into custody.
</p>
<p style="color:#aaa; font-size:0.9em;">Suspicion reached 100/100.</p>
<div style="margin-top:20px;">
<<button "New Game">><<goto "Age Verification">><</button>>
</div>
</div>
<<else>>
<<nobr>>
<<set _tier = window.getSuspicionTier()>>
<<set _log = State.temporary.dayLog || []>>
<<set _lvl = $parasiteLevel || 1>>
<<set _lvlName = [null,"Hatchling","Juvenile","Mature","Apex"][_lvl]>>
<<set _lvlCol = [null,"#88aaff","#44cc88","#ffaa44","#ff5555"][_lvl]>>
<<set _inf = window.getHivemindLoad()>>
<<set _vectors = $roster.filter(id => State.variables[id] && State.variables[id].corr >= 100).length>>
<<set _nestList = Object.keys($nests).filter(k => $nests[k] && $nests[k].level > 0)>>
<<set _nests = _nestList.length>>
<<set _breed = _nestList.filter(k => $nests[k].type === "breeding").length>>
<<set _cap = window.getCorrCap ? window.getCorrCap() : 25>>
<<set _sc = window.getSuspicionColor()>>
<<set _sl = window.getSuspicionLabel()>>
<<set _infCol = _inf >= $hivemindCap ? "#ff5555" : _inf >= Math.floor($hivemindCap * 0.75) ? "#ffaa44" : "#bd59ff">>
<<set _nstCol = _nests >= $nestCap ? "#ff5555" : "#bd59ff">>
<<set _infPct = Math.min(100, Math.round((_inf / Math.max(1,$hivemindCap)) * 100))>>
<<set _nstPct = Math.min(100, Math.round((_nests / Math.max(1,$nestCap)) * 100))>>
<<set _alert = null>>
<<if _tier >= 3>>
<<set _alert = { c:"#ff2222", bg:"#2a0000", t:"⛔ DANGER — PUBLIC ACCESS DENIED",
d:"Police are actively investigating. Infected individuals may be arrested." }>>
<<elseif _tier >= 2>>
<<set _alert = { c:"#ff8800", bg:"#1a0d00", t:"⚠ HIGH SUSPICION — MOVEMENT RESTRICTED",
d:"Officers may destroy nests and patrol aggressively overnight." }>>
<<elseif _tier >= 1>>
<<set _alert = { c:"#ffcc00", bg:"#1a1500", t:"🔍 ELEVATED — UNDER SURVEILLANCE",
d:"A detective has been assigned. They may appear near infected individuals." }>>
<</if>>
<<if $pendingParties and $pendingParties.length > 0 and $suspicion >= 50>>
<<set _partiesCancelled = true>>
<<set $pendingParties = []>>
<<else>>
<<set _partiesCancelled = false>>
<</if>>
<</nobr>>
<div style="max-width:1100px; margin:0 auto;">
/* ── HEADER ── */
<div style="display:flex; justify-content:space-between; align-items:baseline; border-bottom:1px solid #222; padding-bottom:8px; margin-bottom:14px;">
<h1 style="margin:0; font-size:1.5em;">Night Report</h1>
<span style="color:#555; font-size:0.85em;">Day $day · $weekDay</span>
</div>
/* ── ALERTS ── */
<<if _alert>>
<div @style="'background:' + _alert.bg + '; border-left:3px solid ' + _alert.c + '; border-radius:4px; padding:8px 12px; margin-bottom:10px;'">
<span @style="'color:' + _alert.c + '; font-weight:bold; font-size:0.9em;'"><<print _alert.t>></span>
<span style="color:#888; font-size:0.82em; margin-left:8px;"><<print _alert.d>></span>
</div>
<</if>>
<<if _partiesCancelled>>
<div style="background:#1a0010; border-left:3px solid #ff6688; border-radius:4px; padding:7px 12px; margin-bottom:10px; font-size:0.85em;">
<span style="color:#ff6688; font-weight:bold;">🚫 All parties cancelled</span>
<span style="color:#777; margin-left:6px;">Suspicion too high to socialise safely.</span>
</div>
<</if>>
/* ══ TWO-COLUMN: EVENTS LEFT, STATUS RIGHT ══ */
<div class="dayend-grid" style="display:flex; gap:14px; align-items:flex-start; flex-wrap:wrap;">
/* ── EVENTS (primary) ── */
<div style="flex:1 1 460px; min-width:300px;">
<div style="font-size:0.7em; text-transform:uppercase; letter-spacing:0.12em; color:#6a0dad; margin-bottom:8px;">
Overnight<<if _log.length > 0>> · <<print _log.length>> event<<if _log.length !== 1>>s<</if>><</if>>
</div>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-radius:8px; padding:12px 16px;">
/* Grouped rather than printed in raw execution order — see
window.groupDayLog in JS-Core. Sections with nothing in them are
dropped, so a quiet night is still short. */
<<if _log.length > 0>>
<<set _sections = window.groupDayLog(_log)>>
<<for _si, _sec range _sections>>
<<capture _si _sec>>
<<if _sec.label>>
<div style="font-size:0.68em; text-transform:uppercase; letter-spacing:0.1em; font-weight:bold; color:<<print _sec.colour>>; margin:<<if _si gt 0>>14px<<else>>0<</if>> 0 5px;">
<<print _sec.label>>
</div>
<</if>>
<<for _li, _line range _sec.lines>>
<<capture _li _line>>
<div style="font-size:0.88em; color:#bbb; line-height:1.6; padding:4px 0 4px 9px; border-left:2px solid <<print _sec.colour>>33; <<if _li lt _sec.lines.length - 1>>border-bottom:1px solid #151515;<</if>>">
<<print _line>>
</div>
<</capture>>
<</for>>
<</capture>>
<</for>>
<<else>>
<p style="color:#3a3a3a; margin:0; font-style:italic; font-size:0.88em;">A quiet night. Nothing stirred.</p>
<</if>>
</div>
</div>
/* ── STATUS (secondary) ── */
<div style="flex:0 1 320px; min-width:260px; display:flex; flex-direction:column; gap:10px;">
/* Parasite level */
<div style="background:#0d0d1a; border:1px solid #2a0050; border-radius:8px; padding:10px 14px;">
<div style="display:flex; justify-content:space-between; align-items:baseline;">
<span style="color:#555; font-size:0.72em; text-transform:uppercase; letter-spacing:0.08em;">Parasite</span>
<span @style="'color:' + _lvlCol + '; font-weight:bold; font-size:0.95em;'"><<print _lvlName>> · L<<print _lvl>></span>
</div>
<div style="display:flex; justify-content:space-between; margin-top:8px; font-size:0.85em;">
<span style="color:#888;">Parasites</span>
<b style="color:#bd59ff;"><<print $parasite>></b>
</div>
<div style="display:flex; justify-content:space-between; margin-top:3px; font-size:0.85em;">
<span style="color:#888;">Infection power</span>
<b style="color:#00cc44;"><<print $infectionPower>></b>
</div>
<div style="display:flex; justify-content:space-between; margin-top:3px; font-size:0.85em;">
<span style="color:#888;">Corruption cap</span>
<b style="color:#cc88ff;"><<print _cap>></b>
</div>
</div>
/* Hivemind */
<div style="background:#0d0d1a; border:1px solid #2a0050; border-radius:8px; padding:10px 14px;">
<div style="display:flex; justify-content:space-between; align-items:baseline; margin-bottom:6px;">
<span style="color:#555; font-size:0.72em; text-transform:uppercase; letter-spacing:0.08em;">🧠 Hivemind</span>
<span @style="'color:' + _infCol + '; font-weight:bold; font-size:0.95em;'"><<print _inf>> / <<print $hivemindCap>></span>
</div>
<div style="background:#1a1a1a; border-radius:3px; height:5px; overflow:hidden;">
<div @style="'width:' + _infPct + '%; height:100%; background:' + _infCol + ';'"></div>
</div>
<div style="color:#555; font-size:0.75em; margin-top:5px;">
/* Vectors occupy slots like everyone else, so this is a
reach figure, not a discount. Saying "free" here was the
old exemption talking. */
<<if _vectors > 0>>
<span style="color:#ff4444;"><<print _vectors>> Vector<<if _vectors !== 1>>s<</if>></span> — spreading on their own
<<else>>
No Vectors yet
<</if>>
</div>
</div>
/* Nests */
<div style="background:#0d0d1a; border:1px solid #2a0050; border-radius:8px; padding:10px 14px;">
<div style="display:flex; justify-content:space-between; align-items:baseline; margin-bottom:6px;">
<span style="color:#555; font-size:0.72em; text-transform:uppercase; letter-spacing:0.08em;">🪹 Nests</span>
<span @style="'color:' + _nstCol + '; font-weight:bold; font-size:0.95em;'"><<print _nests>> / <<print $nestCap>></span>
</div>
<div style="background:#1a1a1a; border-radius:3px; height:5px; overflow:hidden;">
<div @style="'width:' + _nstPct + '%; height:100%; background:' + _nstCol + ';'"></div>
</div>
<div style="color:#555; font-size:0.75em; margin-top:5px;">
<<if _nests is 0>>None planted
<<elseif _breed > 0>><<print _breed>> breeding · <<print _nests - _breed>> spreading
<<else>>All spreading<</if>>
</div>
</div>
/* Suspicion */
<div style="background:#0d0d0d; border:1px solid #1e1e1e; border-radius:8px; padding:10px 14px;">
<div style="display:flex; justify-content:space-between; align-items:baseline; margin-bottom:6px;">
<span style="color:#555; font-size:0.72em; text-transform:uppercase; letter-spacing:0.08em;">Suspicion</span>
<span @style="'color:' + _sc + '; font-weight:bold; font-size:0.95em;'"><<print _sl>> · <<print $suspicion>></span>
</div>
<div style="background:#1a1a1a; border-radius:3px; height:5px; overflow:hidden;">
<div @style="'width:' + $suspicion + '%; height:100%; background:' + _sc + '; transition:width 0.3s;'"></div>
</div>
</div>
</div>
</div>
<div style="text-align:center; margin-top:18px;">
<<button "Wake Up">>
<<if window.canUnlockHarem()>>
<<run window.unlockHarem()>>
<<goto "HaremUnlockScene">>
<<else>>
<<goto "DayStart">>
<</if>>
<</button>>
</div>
</div>
<</if>>/* Explicit destination rather than a back macro. `back` REWINDS the variable
state to before this passage was entered instead of navigating, so anything
done here is discarded -- and with no history it cannot resolve at all. */
[[← Back to the Hub|TownHub]]
<<nobr>>
<<set _lvl = $parasiteLevel || 1>>
<<set _typeColors = {
"individual": "#bd59ff",
"corruption": "#cc66ff",
"faction": "#ffcc00",
"spread": "#44aaff",
"group": "#ff8844",
"location": "#44ffaa",
"locationCount": "#44ffaa",
"classRoster": "#ffcc44"
}>>
<<set _typeSections = [
{ type: "meet", color: "#44ddff", borderColor: "#00303a", barColor: "#2288aa", title: "Make Contact" },
{ type: "corruption", color: "#bd59ff", borderColor: "#2a0040", barColor: "#9c27b0", title: "Corruption Targets" },
{ type: "individual", color: "#cc66ff", borderColor: "#2a0050", barColor: "#7722bb", title: "Corruption (legacy)" },
{ type: "faction", color: "#ffcc00", borderColor: "#3a2a00", barColor: "#cc9900", title: "Faction Domination" },
{ type: "spread", color: "#44aaff", borderColor: "#001a3a", barColor: "#2266aa", title: "Spread Milestones" },
{ type: "group", color: "#ff8844", borderColor: "#2a1400", barColor: "#aa4400", title: "Group Corruption" },
{ type: "location", color: "#44ffaa", borderColor: "#003a2a", barColor: "#228844", title: "Location Domination" },
{ type: "locationCount", color: "#44ffaa", borderColor: "#003a2a", barColor: "#228844", title: "Domination Milestones" },
{ type: "classRoster", color: "#ffcc44", borderColor: "#2a2000", barColor: "#998800", title: "Class Corruption" }
]>>
<h1 style="text-align:center; color:#bd59ff; margin-bottom:4px;">🎯 Parasite Goals</h1>
<<set _rrCost = window.GOAL_REROLL_COST || 5>>
<div style="text-align:center; color:#555; font-size:0.9em; margin-bottom:6px;">
<<print $goals.length>> active · <<print $goalsCompleted.length>> completed
· Level <<print _lvl>> · <span style="color:#bd59ff;"><<print $parasite>></span> parasites
</div>
<<if $goalActionMsg>>
<div style="text-align:center; margin-bottom:10px;">
<span style="color:#cc88ff; font-size:0.85em; background:#12001a; border:1px solid #6a0dad; border-radius:14px; padding:3px 12px;">
<<print $goalActionMsg>>
</span>
</div>
<<set $goalActionMsg = "">>
<</if>>
<<if $goalJustCompleted>>
<div style="text-align:center; margin-bottom:12px;">
<span style="color:#ffcc00; font-weight:bold; font-size:1em; padding:4px 14px; background:#1a1400; border:1px solid #ffcc00; border-radius:20px;">
✓ Goal completed!
</span>
</div>
<<set $goalJustCompleted = false>>
<</if>>
<<if $goals.length is 0>>
<div style="text-align:center; color:#444; padding:40px 0; font-style:italic; font-size:0.95em;">
No active goals. They will refresh tomorrow.
</div>
<<else>>
/* ── GOAL SECTIONS BY TYPE ── */
<<for _sec range _typeSections>><<capture _sec>>
<<set _typeGoals = $goals.filter(g => g.type is _sec.type)>>
<<if _typeGoals.length > 0>>
<div style="margin-bottom:22px;">
<div style="font-size:0.78em; font-weight:bold; text-transform:uppercase; letter-spacing:0.1em; margin-bottom:10px; padding-bottom:5px; border-bottom:1px solid <<print _sec.borderColor>>; color:<<print _sec.color>>;">
<<print _sec.title>>
</div>
<<for _g range _typeGoals>><<capture _g _sec>>
<<set _prog = window.getGoalProgress(_g)>>
<<set _done = _prog.pct >= 100>>
<<set _label = window.goalLabel(_g.type, _g.target)>>
<<set _rewardLabel = window.goalRewardLabel(_g.type, _g.target)>>
<<set _rewardPt = ({ meet: 3, individual: 8, corruption: 8, faction: 10, location: 5, locationCount: 8, classRoster: 6 })[_g.type] || 0>>
/* Portrait for individual/corruption goals */
<<set _charId = null>>
<<if _g.type is "individual" or _g.type is "meet">>
<<set _charId = _g.target>>
<<elseif _g.type is "corruption">>
<<set _charId = _g.target.id>>
<</if>>
<<set _charObj = _charId ? State.variables[_charId] : null>>
<div style="background:<<if _done>>#0d1f0d<<else>>#111<</if>>; border:1px solid <<if _done>>#1a5a1a<<else>>#2a2a2a<</if>>; border-radius:8px; padding:12px; margin-bottom:8px;">
<div style="display:flex; gap:12px; align-items:flex-start;">
/* Portrait (when applicable) */
<<if _charObj and (_charObj.met or _g.type is "meet")>>
<<capture _charId _charObj>>
<div style="flex-shrink:0;">
<img @src="window.getPortraitPath(_charObj.name)"
@style="'width:54px; height:81px; border-radius:6px; object-fit:cover; object-position:top; border:1px solid <<print _sec.color>>44;' + (_charObj.met ? '' : ' filter:brightness(0.35) grayscale(1);')">
</div>
<</capture>>
<</if>>
<div style="flex:1; min-width:0;">
/* Header */
<div style="display:flex; justify-content:space-between; align-items:baseline; margin-bottom:6px; gap:8px;">
<span style="color:<<if _done>>#55cc55<<else>>#ccc<</if>>; font-size:0.95em; font-weight:bold;">
<<if _done>>✓ <</if>><<print _label>>
</span>
<<if _done>>
<span style="color:#44cc88; font-size:0.82em; font-weight:bold; flex-shrink:0;">Ready!</span>
<<else>>
<span style="color:#555; font-size:0.8em; flex-shrink:0;"><<print _prog.current>>/<<print _prog.target>></span>
<</if>>
</div>
/* Progress bar */
<div style="background:#1a1a1a; height:7px; border-radius:4px; overflow:hidden; margin-bottom:6px;">
<div @style="'width:' + _prog.pct + '%; height:100%; border-radius:4px; background:' + ((_done) ? '#44cc88' : '<<print _sec.barColor>>') + '; transition:width 0.3s;'"></div>
</div>
/* Meeting hint */
<<if _g.type is "meet">>
<<set _hint = window.getMeetingHint ? window.getMeetingHint(_g.target) : "">>
<<if _hint>>
<div style="font-size:0.8em; color:#44ddff; margin-bottom:6px;">
📍 <<print _hint>>
</div>
<</if>>
<</if>>
/* Difficulty + reward */
<div style="display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:4px;">
<<if _g.difficulty>>
<span style="font-size:0.75em; color:#444; text-transform:uppercase; letter-spacing:0.06em;">
<<print _g.difficulty>>
</span>
<</if>>
<div style="font-size:0.8em; color:#555;">
Reward:
<<if _rewardPt > 0>><span style="color:#bd59ff;">+<<print _rewardPt>>pt</span><</if>>
<<if _rewardLabel>>
<<if _rewardPt > 0>><span style="color:#444;"> · </span><</if>>
<span style="color:<<print _sec.color>>;"><<print _rewardLabel>></span>
<</if>>
</div>
<<if !_done>>
<<capture _g>>
<span class="loc-btn-wrapper">
<<if $parasite >= _rrCost>>
<<set _rrLbl = "⟳ Reroll (" + _rrCost + "pt)">>
<<button _rrLbl>>
<<set _rr = window.rerollGoal(_g.id)>>
<<set $goalActionMsg = _rr.msg>>
<<goto "Goals">>
<</button>>
<<else>>
<span style="color:#333; font-size:0.75em; font-style:italic;">⟳ <<print _rrCost>>pt</span>
<</if>>
</span>
<</capture>>
<</if>>
</div>
</div>
</div>
</div>
<</capture>><</for>>
</div>
<</if>>
<</capture>><</for>>
<</if>>
/* The empty-slot "Commission" panel was removed. buyNewGoal() never worked
in practice, and slots refill on their own from the nightly roll.
_rrCost is kept below - the Reroll button still uses it. */
/* ── ACTIVE BONUSES ── */
<<if $goalBonuses>>
<<set _hasBonuses =
($goalBonuses.upgradeBonus > 0) or
($goalBonuses.passiveParasite > 0) or
$goalBonuses.noSuspicionIntimate or
$goalBonuses.noSuspicionSchool or
$goalBonuses.noSuspicionAll or
($goalBonuses.corruptedLocations and $goalBonuses.corruptedLocations.length > 0)>>
<<if _hasBonuses>>
<div style="background:#0a0a0a; border:1px solid #1e3a1e; border-radius:8px; padding:14px; margin-bottom:20px;">
<div style="font-size:0.78em; font-weight:bold; color:#44ff88; text-transform:uppercase; letter-spacing:0.1em; margin-bottom:10px;">
✦ Active Bonuses
</div>
<<if $goalBonuses.upgradeBonus > 0>>
<div style="font-size:0.9em; color:#ccc; margin-bottom:5px;">
⬆ Infection Power +<<print $goalBonuses.upgradeBonus>>
</div>
<</if>>
<<if $goalBonuses.passiveParasite > 0>>
<div style="font-size:0.9em; color:#ccc; margin-bottom:5px;">
☣ +<<print $goalBonuses.passiveParasite>> parasite/day
</div>
<</if>>
<<if $goalBonuses.noSuspicionIntimate>>
<div style="font-size:0.9em; color:#ccc; margin-bottom:5px;">
🔇 No suspicion in intimate locations
</div>
<</if>>
<<if $goalBonuses.noSuspicionSchool>>
<div style="font-size:0.9em; color:#ccc; margin-bottom:5px;">
🔇 No suspicion in school locations
</div>
<</if>>
<<if $goalBonuses.noSuspicionAll>>
<div style="font-size:0.9em; color:#ccc; margin-bottom:5px;">
🔇 Suspicion permanently neutralised
</div>
<</if>>
<<if $goalBonuses.corruptedLocations and $goalBonuses.corruptedLocations.length > 0>>
<div style="font-size:0.9em; color:#ccc; margin-bottom:5px;">
☣ Dominated: <span style="color:#bd59ff;"><<print $goalBonuses.corruptedLocations.join(", ")>></span>
</div>
<</if>>
</div>
<</if>>
<</if>>
/* ── COMPLETED GOALS ── */
<<if $goalsCompleted.length > 0>>
<details style="margin-top:10px;">
<summary style="font-size:0.88em; color:#555; cursor:pointer; user-select:none; padding:8px 0; list-style:none;">
▸ Completed goals (<<print $goalsCompleted.length>>) — permanently recorded, never repeat
</summary>
<div style="margin-top:8px; display:flex; flex-direction:column; gap:4px;">
<<for _cg range $goalsCompleted>><<capture _cg>>
<<set _cgLabel = window.goalLabel(_cg.type, _cg.target)>>
<div style="background:#0a0a0a; border:1px solid #1a1a1a; border-radius:5px; padding:8px 12px; display:flex; justify-content:space-between; align-items:center;">
<span style="font-size:0.88em; color:#333; text-decoration:line-through;"><<print _cgLabel>></span>
<span style="font-size:0.78em; color:#2a2a2a; flex-shrink:0; margin-left:8px;">Day <<print _cg.day || _cg.dayAdded || "?">></span>
</div>
<</capture>><</for>>
</div>
</details>
<</if>>
<</nobr>>/* =======================================================================
CHEAT MENU — fully self-contained.
All helpers are defined here; no other passage needs to change.
======================================================================= */
<<script>>
(function () {
/* Status bar HTML, rebuilt after every action */
window.cheatStatus = function () {
var sv = State.variables;
var cap = window.getGlobalCorrCap ? window.getGlobalCorrCap() : 25;
var load = window.getHivemindLoad ? window.getHivemindLoad() : "?";
return '<span style="color:#bd59ff;">' + (sv.parasite || 0) + '</span> parasites · ' +
'Level <span style="color:#bd59ff;">' + (sv.parasiteLevel || 1) + '</span> · ' +
'Nests <span style="color:#44ff88;">' + (sv.nestCap || 0) + '</span> · ' +
'Hivemind <span style="color:#44aaff;">' + load + '/' + (sv.hivemindCap || 0) + '</span> · ' +
'Power <span style="color:#ff8844;">' + (sv.infectionPower || 0) + '</span> · ' +
'Susp <span style="color:#ff4444;">' + (sv.suspicion || 0) + '</span> · ' +
'Corr cap <span style="color:#cc88ff;">' + cap + '</span>';
};
/* ── Evolve one level: mirrors evoluteParasiteLevel() minus cost/requirements ── */
window.cheatEvolve = function () {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
if (lvl >= 4) { sv.cheatMsg = "Already at max level (4)."; return; }
sv.parasiteLevel = lvl + 1;
sv.nestCap = (sv.nestCap || 2) + 2;
sv.hivemindCap = (sv.hivemindCap || 5) + 10;
sv.infectionPower = (sv.infectionPower || 1) + 1;
sv.pendingLevelUpScene = sv.parasiteLevel;
sv.cheatMsg = "Evolved to level " + sv.parasiteLevel +
" (+2 nests, +10 hivemind, +1 power). Level-up scene queued.";
};
/* ── Unlock upgrades. mode: "tier" = current tier only, "upto" = tier <= level, "all" ── */
window.cheatUnlock = function (mode) {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
var defs = window.UPGRADE_DEFS || [];
var n = 0;
if (!sv.upgrades) sv.upgrades = {};
if (mode === "all") {
defs.forEach(function (d) { if (!sv.upgrades[d.id]) n++; sv.upgrades[d.id] = true; });
/* Catch any flag present in $upgrades with no UPGRADE_DEFS entry */
Object.keys(sv.upgrades).forEach(function (k) { sv.upgrades[k] = true; });
sv.parasiteLevel = 4;
/* Deliberately NOT touching nestCap / hivemindCap / infectionPower
— those have their own buttons above. Unlocking upgrades should
not silently max your resource ceilings too. */
sv.cheatMsg = "All upgrades unlocked, parasite level 4. Caps untouched.";
return;
}
defs.forEach(function (d) {
var ok = (mode === "tier") ? (d.tier === lvl) : (d.tier <= lvl);
if (ok && sv.upgrades[d.id] !== true) { sv.upgrades[d.id] = true; n++; }
});
sv.cheatMsg = n + " upgrade(s) unlocked " +
(mode === "tier" ? "at tier " + lvl + "." : "up to tier " + lvl + ".");
};
/* ── Corruption cap: 25 / 50 / 75 / 100 ── */
window.cheatSetCap = function (target) {
var sv = State.variables;
if (!sv.upgrades) sv.upgrades = {};
sv.upgrades.corrCapUnlock1 = (target >= 50);
sv.upgrades.corrCapUnlock2 = (target >= 75);
sv.upgrades.corrCapUnlock3 = (target >= 100);
sv.cheatMsg = "Global corruption cap set to " + window.getGlobalCorrCap() + ".";
};
/* ── Corrupt the whole roster ── */
window.cheatCorruptAll = function (target) {
var sv = State.variables;
if (!sv.upgrades) sv.upgrades = {};
/* Raise the global cap so the value is not clamped back down by nightly ticks */
if (target >= 50) sv.upgrades.corrCapUnlock1 = true;
if (target >= 75) sv.upgrades.corrCapUnlock2 = true;
if (target >= 100) sv.upgrades.corrCapUnlock3 = true;
var n = 0;
sv.roster.forEach(function (id) {
var c = sv[id];
if (!c) return;
c.corr = target;
if (target > 0) { window.recordInfection(c, "cheat", c.location); }
else { c.infected = false; c.breed = false; }
n++;
});
sv.cheatMsg = n + " girl(s) set to corruption " + target +
(target > 0 ? ". Cap raised to " + window.getGlobalCorrCap() + "." : " and cleared.");
};
window.cheatMeetAll = function () {
var sv = State.variables, n = 0;
sv.roster.forEach(function (id) {
if (sv[id] && !sv[id].met) { sv[id].met = true; n++; }
});
sv.cheatMsg = n + " character(s) met.";
};
window.cheatInfectMet = function () {
var sv = State.variables, n = 0;
sv.roster.forEach(function (id) {
var c = sv[id];
if (c && c.met && !c.infected && !c.arrested) {
window.recordInfection(c, "cheat", c.location);
if (!c.corr || c.corr < 1) c.corr = 1;
n++;
}
});
var load = window.getHivemindLoad ? window.getHivemindLoad() : "?";
sv.cheatMsg = n + " girl(s) infected. Hivemind load " + load + "/" + sv.hivemindCap + ".";
};
window.cheatFreeArrested = function () {
var sv = State.variables, n = 0;
sv.roster.forEach(function (id) {
var c = sv[id];
if (c && c.arrested) { c.arrested = false; c.location = null; n++; }
});
sv.cheatMsg = n + " girl(s) released from The Lab.";
};
window.cheatDiscoverAll = function () {
var sv = State.variables, n = 0;
(sv.locations || []).forEach(function (l) {
if (l.harem) return; /* Harem Mansion has its own unlock */
if (!l.unlocked) { l.unlocked = true; n++; }
});
sv.blockedLocations = [];
sv.cheatMsg = n + " location(s) unlocked. Police blocks cleared.";
};
window.cheatUnlockHarem = function () {
var sv = State.variables;
var loc = (sv.locations || []).find(function (l) { return l.name === "Harem Mansion"; });
if (!loc) { sv.cheatMsg = "Harem Mansion not found in $locations."; return; }
loc.unlocked = true;
sv.haremUnlocked = true;
if (!sv.haremFinancier) {
var f = (window.RICH_WOMEN || []).find(function (id) { return sv[id]; });
sv.haremFinancier = f || null;
}
sv.cheatMsg = "Harem Mansion unlocked.";
};
window.cheatSuspicion = function (value, relative) {
var sv = State.variables;
var v = relative ? (sv.suspicion || 0) + value : value;
sv.suspicion = Math.max(0, Math.min(99, v));
if (sv.suspicion < 25) sv.detectiveActive = false;
sv.cheatMsg = "Suspicion set to " + sv.suspicion + ".";
};
window.cheatBump = function (field, amount) {
var sv = State.variables;
var base = { nestCap: 2, hivemindCap: 5, infectionPower: 1 };
sv[field] = (sv[field] || base[field] || 0) + amount;
sv.cheatMsg = field + " → " + sv[field];
};
window.cheatSet = function (field, value, label) {
var sv = State.variables;
sv[field] = value;
sv.cheatMsg = label;
};
/* ── Parasites: relative bump, floored at 0 ── */
window.cheatBumpParasite = function (amount) {
var sv = State.variables;
var before = sv.parasite || 0;
sv.parasite = Math.max(0, before + amount);
var delta = sv.parasite - before;
sv.cheatMsg = (delta >= 0 ? "+" : "") + delta + " parasites \u2192 " + sv.parasite + ".";
};
window.cheatSetParasite = function (value) {
var sv = State.variables;
sv.parasite = Math.max(0, value);
sv.cheatMsg = "Parasites set to " + sv.parasite + ".";
};
})();
<</script>>
[[← Back to the Hub|TownHub]]
<h1 style="text-align:center; color:#bd59ff; margin-bottom:2px;">☣ Cheats</h1>
<div style="text-align:center; color:#555; font-size:0.82em; margin-bottom:14px; font-style:italic;">
Debug menu. Nothing here costs parasites or checks requirements.
</div>
<div id="cheat-status" style="max-width:600px; margin:0 auto 6px; background:#0d0d1a; border:1px solid #6a0dad; border-radius:6px; padding:8px 12px; text-align:center; color:#ccc; font-size:0.85em;"><<print window.cheatStatus()>></div>
<div id="cheat-msg" style="max-width:600px; margin:0 auto 18px; text-align:center; color:#44cc88; font-size:0.85em; min-height:1.3em;"></div>
<div style="max-width:600px; margin:0 auto;">
/* ═══════════════ PARASITES ═══════════════ */
<div style="color:#bd59ff; font-size:0.78em; font-weight:bold; text-transform:uppercase; letter-spacing:0.1em; border-bottom:1px solid #2a1a3a; padding-bottom:4px; margin:16px 0 8px;">Parasites</div>
<div style="display:flex; flex-wrap:wrap; gap:6px; align-items:center;">
<<button "🧬 +20 parasites">>
<<run window.cheatBumpParasite(20)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "+5">>
<<run window.cheatBumpParasite(5)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "+100">>
<<run window.cheatBumpParasite(100)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "−5">>
<<run window.cheatBumpParasite(-5)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "Wipe">>
<<run window.cheatSetParasite(0)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
/* ═══════════════ CAPS & RESOURCES ═══════════════ */
<div style="color:#bd59ff; font-size:0.78em; font-weight:bold; text-transform:uppercase; letter-spacing:0.1em; border-bottom:1px solid #2a1a3a; padding-bottom:4px; margin:20px 0 8px;">Caps & Resources</div>
<div style="display:flex; flex-wrap:wrap; gap:6px;">
<<button "🪺 Nest cap → 999">>
<<run window.cheatSet("nestCap", 999, "Nest cap set to 999.")>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "🧠 Hivemind cap → 9999">>
<<run window.cheatSet("hivemindCap", 9999, "Hivemind cap set to 9999.")>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
<div style="color:#666; font-size:0.78em; margin:12px 0 4px;">Increment by 1 or 5</div>
<table style="width:100%; border-collapse:collapse; font-size:0.9em;">
<tr>
<td style="padding:3px 8px 3px 0; color:#ff8844; width:130px;">Infection Power</td>
<td style="padding:3px;"><<button "+1">>
<<run window.cheatBump("infectionPower", 1)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>></td>
<td style="padding:3px;"><<button "+5">>
<<run window.cheatBump("infectionPower", 5)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>></td>
</tr>
<tr>
<td style="padding:3px 8px 3px 0; color:#44aaff;">Hivemind Cap</td>
<td style="padding:3px;"><<button "+1">>
<<run window.cheatBump("hivemindCap", 1)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>></td>
<td style="padding:3px;"><<button "+5">>
<<run window.cheatBump("hivemindCap", 5)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>></td>
</tr>
<tr>
<td style="padding:3px 8px 3px 0; color:#44ff88;">Nest Cap</td>
<td style="padding:3px;"><<button "+1">>
<<run window.cheatBump("nestCap", 1)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>></td>
<td style="padding:3px;"><<button "+5">>
<<run window.cheatBump("nestCap", 5)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>></td>
</tr>
</table>
/* ═══════════════ EVOLUTION & UPGRADES ═══════════════ */
<div style="color:#bd59ff; font-size:0.78em; font-weight:bold; text-transform:uppercase; letter-spacing:0.1em; border-bottom:1px solid #2a1a3a; padding-bottom:4px; margin:20px 0 8px;">Evolution & Upgrades</div>
<div style="display:flex; flex-wrap:wrap; gap:6px;">
<<button "⬆ Evolve parasite (+1 level)">>
<<run window.cheatEvolve()>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "⭐ Jump to level 4">>
<<run window.cheatSet("parasiteLevel", 4, "Parasite level set to 4 (no level-up scene).")>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
<div style="display:flex; flex-wrap:wrap; gap:6px; margin-top:6px;">
<<button "🔓 Unlock this tier only">>
<<run window.cheatUnlock("tier")>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "🔓 Unlock all tiers ≤ level">>
<<run window.cheatUnlock("upto")>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "💥 UNLOCK EVERYTHING">>
<<run window.cheatUnlock("all")>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
<div style="color:#666; font-size:0.76em; margin-top:6px;">
53 upgrades exist — 6 at tier 1, 13 at tier 2, 22 at tier 3, 12 at tier 4. Tier gating uses <code>UPGRADE_DEFS[].tier</code>, so nothing is hardcoded here.
</div>
/* ═══════════════ CORRUPTION CAPS ═══════════════ */
<div style="color:#bd59ff; font-size:0.78em; font-weight:bold; text-transform:uppercase; letter-spacing:0.1em; border-bottom:1px solid #2a1a3a; padding-bottom:4px; margin:20px 0 8px;">Corruption Caps</div>
<div style="color:#666; font-size:0.78em; margin-bottom:6px;">
Sets the three <code>corrCapUnlock</code> flags — the only thing <code>getGlobalCorrCap()</code> reads. Per-girl <code>capBreaks</code> stack on top of this.
</div>
<div style="display:flex; flex-wrap:wrap; gap:6px;">
<<button "Cap → 25 (reset)">>
<<run window.cheatSetCap(25)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "Cap → 50">>
<<run window.cheatSetCap(50)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "Cap → 75">>
<<run window.cheatSetCap(75)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "Cap → 100">>
<<run window.cheatSetCap(100)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
/* ═══════════════ GIRLS ═══════════════ */
<div style="color:#bd59ff; font-size:0.78em; font-weight:bold; text-transform:uppercase; letter-spacing:0.1em; border-bottom:1px solid #2a1a3a; padding-bottom:4px; margin:20px 0 8px;">Girls</div>
<div style="color:#666; font-size:0.78em; margin-bottom:6px;">
Corrupting also sets <code>infected</code> and raises the global cap to match, so nightly ticks don't clamp it back down.
</div>
<div style="display:flex; flex-wrap:wrap; gap:6px;">
<<button "Corrupt all → 25">>
<<run window.cheatCorruptAll(25)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "→ 50">>
<<run window.cheatCorruptAll(50)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "→ 75">>
<<run window.cheatCorruptAll(75)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "→ 100">>
<<run window.cheatCorruptAll(100)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "→ 0 (wipe)">>
<<run window.cheatCorruptAll(0)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
<div style="display:flex; flex-wrap:wrap; gap:6px; margin-top:6px;">
<<button "👥 Meet all characters">>
<<run window.cheatMeetAll()>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "☣ Infect all met girls">>
<<run window.cheatInfectMet()>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "🔓 Free all arrested">>
<<run window.cheatFreeArrested()>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
/* ═══════════════ WORLD ═══════════════ */
<div style="color:#bd59ff; font-size:0.78em; font-weight:bold; text-transform:uppercase; letter-spacing:0.1em; border-bottom:1px solid #2a1a3a; padding-bottom:4px; margin:20px 0 8px;">World</div>
<div style="display:flex; flex-wrap:wrap; gap:6px;">
<<button "🗺 Discover all locations">>
<<run window.cheatDiscoverAll()>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "🍾 Unlock Harem Mansion">>
<<run window.cheatUnlockHarem()>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
<div style="color:#666; font-size:0.78em; margin:12px 0 4px;">Suspicion — 25 assigns a detective, 50 starts raids and suspicion scenes, 75 starts arrests. Clamped to 0–99.</div>
<div style="display:flex; flex-wrap:wrap; gap:6px; align-items:center;">
<<button "−25">>
<<run window.cheatSuspicion(-25, true)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "−10">>
<<run window.cheatSuspicion(-10, true)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "−5">>
<<run window.cheatSuspicion(-5, true)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "−1">>
<<run window.cheatSuspicion(-1, true)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<span id="cheat-susp" style="display:inline-block; min-width:74px; text-align:center; font-weight:bold; color:#ff4444; background:#1a0d0d; border:1px solid #6a1a1a; border-radius:5px; padding:4px 8px;"><<print $suspicion>></span>
<<button "+1">>
<<run window.cheatSuspicion(1, true)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "+5">>
<<run window.cheatSuspicion(5, true)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "+10">>
<<run window.cheatSuspicion(10, true)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "+25">>
<<run window.cheatSuspicion(25, true)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
<div style="display:flex; flex-wrap:wrap; gap:6px; margin-top:6px;">
<<button "Clear to 0">>
<<run window.cheatSuspicion(0, false)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
<<button "Max (99)">>
<<run window.cheatSuspicion(99, false)>>
<<replace "#cheat-status">><<print window.cheatStatus()>><</replace>>
<<replace "#cheat-susp">><<print $suspicion>><</replace>>
<<replace "#cheat-msg">>✓ <<print $cheatMsg>><</replace>>
<</button>>
</div>
</div>
<div style="text-align:center; margin-top:26px;">
[[← Back to the Hub|TownHub]]
</div><<nobr>>
<<set _c = State.variables[$interactTarget]>>
<<set _method = $infectMethod || "direct">>
<<set _imgSrc = window.getEventImagePath(_c.name)>>
<<set _ups = $upgrades || {}>>
<<set _corrCap = window.getCorrCap ? window.getCorrCap() : 25>>
/* ── HIVEMIND CAP CHECK ── */
/* getHivemindLoad() is the one definition of "how full is the hivemind" and
it excludes captives, who are worked on directly rather than run remotely.
These two lines used to count them, so the number shown here disagreed with
the number the infection gate actually enforced. */
<<set _infectedCount = window.getHivemindLoad()>>
<<set _hivemindFull = window.hivemindFull()>>
/* ── AUTHORITY CHECK ── */
<<set _isAuthority = _c.trait is "authority">>
<<set _authBlocked = _isAuthority and !_ups.infectAuthority>>
/* ── UNMET CHECK ── */
<<set _isUnmet = !_c.met>>
<<set _unmetBlocked = _isUnmet and !_ups.infectUnmet>>
/* ── NEST TYPE GUARD ──
Exposure works by breathing the nest's influence. A breeding nest does not
spread — it only produces parasites — so exposure must be blocked there. */
<<set _nHere = $nests[$currentLocation]>>
<<set _spreadingNest = _nHere && _nHere.level > 0 && (_nHere.type || "spreading") isnot "breeding">>
<<set _exposureBlocked = (_method is "exposure") and !_spreadingNest>>
/* ── VECTOR SOURCE ── */
<<set _vecSrc = ($infectVectorSrc) ? State.variables[$infectVectorSrc] : null>>
/* ── SUCCESS CHANCE BY METHOD ── */
<<set _baseSuccess = 0.60>>
<<if _ups.infectionSuccessRate1>><<set _baseSuccess = Math.min(1.0, _baseSuccess + 0.25)>><</if>>
<<if _method is "direct">>
<<set _successChance = _isAuthority ? (_baseSuccess - 0.20) : _baseSuccess>>
<<set _cost = 1>>
<<elseif _method is "exposure">>
<<set _successChance = _isAuthority ? 0.80 : 0.95>>
<<set _cost = 2>>
<<else>>
<<set _successChance = 0.90>>
<<set _cost = 1>>
<</if>>
<<set _successChance = Math.max(0, Math.min(1, _successChance))>>
/* ── ROLL ── */
<<set _blocked = _hivemindFull or _authBlocked or _unmetBlocked or _exposureBlocked>>
<<set _failed = _blocked or (Math.random() > _successChance)>>
<<if !_blocked>><<set $parasite -= _cost>><</if>>
<</nobr>>
/* ── HEADER ── */
<div style="text-align:center; margin-bottom:16px;">
<img @src="_imgSrc" style="max-width:320px; width:80%; border-radius:10px; border:3px solid <<if _blocked>>#ff2222<<elseif _failed>>#ff4444<<else>>#9c27b0<</if>>; display:block; margin:0 auto 10px;">
<h1 style="color:<<if _blocked>>#ff2222<<elseif _failed>>#ff4444<<else>>#bd59ff<</if>>;">
<<if _blocked>>Blocked<<elseif _failed>>Infection Failed<<else>>Infection Successful<</if>>
</h1>
</div>
/* ── BLOCKED MESSAGES ── */
<<if _hivemindFull>>
<div style="background:#1a0000; border:2px solid #ff2222; border-radius:6px; padding:12px 16px; margin-bottom:16px; text-align:center;">
<div style="color:#ff4444; font-weight:bold; margin-bottom:4px;">🧠 Hivemind at Capacity</div>
<div style="color:#aaa; font-size:0.88em;">
You are controlling <<print _infectedCount>> / <<print $hivemindCap>> girls.<br>
Upgrade your hivemind capacity or evolve the parasite. If neither is available, <em>Strained Expansion</em> in the Upgrades screen always adds a slot.
</div>
</div>
<<elseif _authBlocked>>
<div style="background:#1a0000; border:2px solid #ff2222; border-radius:6px; padding:12px 16px; margin-bottom:16px; text-align:center;">
<div style="color:#ff4444; font-weight:bold; margin-bottom:4px;">⛔ Authority Figure</div>
<div style="color:#aaa; font-size:0.88em;">
<<print _c.name>> is an Authority figure. Unlock <em>Authority Breach</em> in the Upgrades to infect her.
</div>
</div>
<<elseif _exposureBlocked>>
<div style="background:#1a0000; border:2px solid #ff2222; border-radius:6px; padding:12px 16px; margin-bottom:16px; text-align:center;">
<div style="color:#ff4444; font-weight:bold; margin-bottom:4px;">⛔ No Spreading Nest</div>
<div style="color:#aaa; font-size:0.88em;">
Exposure requires a <em>spreading</em> nest here.<br>
A breeding nest produces parasites — it does not spread the infection.
</div>
</div>
<<elseif _unmetBlocked>>
<div style="background:#1a0000; border:2px solid #ff2222; border-radius:6px; padding:12px 16px; margin-bottom:16px; text-align:center;">
<div style="color:#ff4444; font-weight:bold; margin-bottom:4px;">⛔ Unknown Target</div>
<div style="color:#aaa; font-size:0.88em;">
You haven't met this girl. Unlock <em>Blind Reach</em> in the Upgrades to infect unmet targets.
</div>
</div>
/* ── METHOD RESULTS ── */
<<elseif _method is "direct">>
<<if _failed>>
<<if _isAuthority>>
<p>You move toward <<print _c.name>> but something in her bearing stops you cold. Her eyes find yours — alert, suspicious. The parasite recoils before it can take hold.</p>
<p style="color:#ff4444; font-weight:bold;">Her instincts are too sharp. The infection found no purchase.</p>
<<else>>
<p>You reach for <<print _c.name>>, but she shifts at the last moment, instinctively. The contact is incomplete. The parasite dissipates.</p>
<p style="color:#ff8844; font-weight:bold;">The infection failed to take hold.</p>
<</if>>
<<set _failSusp = _isAuthority ? 12 : 6>>
<<run window.addSuspicion(_failSusp)>>
<p style="color:#ff8844; font-size:0.88em;">⚠ The attempt was noticed. (+<<print _failSusp>> suspicion)</p>
<<else>>
<<run window.recordInfection($interactTarget, "direct", $currentLocation)>>
<<if _c.corr <= 0>><<set _c.corr = 1>><</if>>
<p>You move close enough. The parasite finds its moment — a brush of skin, a shared breath — and slips in, unnoticed.</p>
<p style="color:#bd59ff; font-weight:bold;"><<print _c.name>> has been infected.</p>
<<set _witnessMsg = window.checkInfectionWitnesses($interactTarget)>>
<<if _witnessMsg>><<print _witnessMsg>><</if>>
<</if>>
<<elseif _method is "exposure">>
<<if _failed>>
<p>You spend time near <<print _c.name>>, the nest's influence threading outward, but she moves on before the exposure completes.</p>
<p style="color:#ff8844; font-weight:bold;">The prolonged exposure wasn't enough. She slipped away in time.</p>
<<run window.addSuspicion(4)>>
<p style="color:#ff8844; font-size:0.88em;">⚠ (+4 suspicion)</p>
<<else>>
<<run window.recordInfection($interactTarget, "exposure", $currentLocation)>>
<<set _c.corr = Math.min(_corrCap, (_c.corr || 0) + 5)>>
<p>The nest's influence does the heavy work. Over the course of your time here, the parasite saturates the air around her, finding its way in slowly, deeply.</p>
<p style="color:#bd59ff; font-weight:bold;"><<print _c.name>> has been infected. The exposure deepened its hold (+5 corr).</p>
<<set _witnessMsg = window.checkInfectionWitnesses($interactTarget)>>
<<if _witnessMsg>><<print _witnessMsg>><</if>>
<</if>>
<<else>>
/* vector */
<<if _failed>>
<p>
<<if _vecSrc>><<print _vecSrc.name>> moves to introduce you but <<print _c.name>> keeps her distance.
<<else>>The indirect approach fell short.
<</if>>
The parasite found no opening.
</p>
<p style="color:#ff8844; font-weight:bold;">The vector path was blocked. The infection didn't take.</p>
<<run window.addSuspicion(3)>>
<p style="color:#ff8844; font-size:0.88em;">⚠ (+3 suspicion)</p>
<<else>>
<<run window.recordInfection($interactTarget, "vector", $currentLocation)>>
<<if _c.corr <= 0>><<set _c.corr = 1>><</if>>
<<if _vecSrc>>
<p><<print _vecSrc.name>> doesn't know what she's doing, but she's the bridge. A shared moment, a touch, a word — and the parasite travels the connection, crossing from her into <<print _c.name>> before either of them notices.</p>
<<else>>
<p>The network does the work. The parasite flows through existing bonds, reaching <<print _c.name>> through a chain she can't see.</p>
<</if>>
<p style="color:#bd59ff; font-weight:bold;"><<print _c.name>> has been infected through the network.</p>
<<run window.addSuspicion(3)>>
<p style="color:#888; font-size:0.88em;">+3 suspicion (indirect method)</p>
<</if>>
<</if>>
/* ── LEVEL UP CHECK ── */
<<nobr>>
<<if !_failed and !_blocked>>
<<set _oldStage = window.getCorrSuffix(Math.max(0, _c.corr - 1))>>
<<set _newStage = window.getCorrSuffix(_c.corr)>>
<<if _newStage isnot _oldStage and _newStage isnot "Normal">>
<<set $levelUpTarget = $interactTarget>>
<<set $levelUpStage = _newStage>>
<<set $levelUpReturn = "DayEnd">>
<</if>>
<</if>>
<</nobr>>
/* ── SUSPICION STATUS ── */
<<if $suspicion >= 20>>
<div style="background:#1a0000; border:1px solid #ff4444; border-radius:5px; padding:8px 12px; margin-top:12px;">
<p style="color:#ff8844; font-style:italic; font-size:0.88em; margin:0;">⚠ Suspicion: $suspicion / 100</p>
</div>
<</if>>
/* ── EXIT ── */
<div style="text-align:center; margin-top:24px; display:flex; gap:12px; justify-content:center; flex-wrap:wrap;">
<<button "Sleep">>
<<set $infectMethod = "direct">>
<<set $infectVectorSrc = null>>
<<if $levelUpTarget>>
<<set $levelUpReturn = "DayEnd">>
<<goto "CorrLevelUp">>
<<else>>
<<goto "DayEnd">>
<</if>>
<</button>>
</div><<silently>>
<<set _ups = $upgrades || {}>>
<<set _charsHere = []>>
<<set _bredCount = 0>>
<<for _i to 0; _i lt $roster.length; _i++>>
<<set _charId = $roster[_i]>>
<<set _char = State.variables[_charId]>>
<<if _char.location is $currentLocation and _char.corr >= 25 and !_char.arrested>>
<<run _charsHere.push(_charId)>>
/* Her OWN cap — a girl whose cap has been broken must not be
clamped back down to the global ceiling. */
<<set _charCap = window.getCorrCap ? window.getCorrCap(_charId) : 25>>
/* Proximity Effect upgrade: tick all infected girls here */
<<if (_ups.corrTickSameLocation or _ups.corrTickSameLocation2) and _char.infected and _char.corr < _charCap>>
<<set _proxTick = _ups.corrTickSameLocation2 ? 2 : 1>>
<<set _char.corr = Math.min(_charCap, _char.corr + _proxTick)>>
<</if>>
/* Breeding: corruption 75 or more. The old rule ALSO demanded she be at her
personal cap, which made breeding impossible for most of the late game —
once you bought Universal Threshold III (or broke her cap) the ceiling was
100, so a devoted girl at 75, 80 or 90 could never be bred. Only a girl
sitting exactly at her cap qualified, which is why it fired sometimes and
not others. 75 is the Devoted threshold and is the intended gate. */
<<if _char.corr >= 75 and !_char.breed>>
<<set _char.breed = true>>
<<set _bredCount += 1>>
<</if>>
<</if>>
<</for>>
/* Limit to girlsPerScene */
<<set _charsHere = _charsHere.slice(0, ($settings && $settings.girlsPerScene) ? $settings.girlsPerScene : 4)>>
<</silently>>
<h1 style="text-align:center;">Group Activity: $currentLocation</h1>
<div style="background:#000; padding:10px; border:1px solid #333; border-radius:8px;">
<<GroupVideos _charsHere>>
</div>
<div style="text-align:center; margin-top:20px;">
<p>You spend hours indulging with everyone present. The corruption binds them closer to you.</p>
<<if (_ups.corrTickSameLocation or _ups.corrTickSameLocation2)>>
<p style="color:#bd59ff; font-size:0.88em;">☣ Proximity Effect: infected girls here gained +<<print _ups.corrTickSameLocation2 ? 2 : 1>> corruption.</p>
<</if>>
<<if _bredCount > 0>>
<p style="color:#ff5959; font-weight:bold;"><<print _bredCount>> girl<<if _bredCount > 1>>s were<<else>> was<</if>> bred during this session!</p>
<</if>>
/* "Spend Time with All" costs the day, the same as an Activity does — you
spend hours here. Activity ends on Sleep alone for exactly that reason,
and this offered a free walk back to the hub, which let the player run
the group scene and then still do everything else. */
<div style="display:flex; gap:12px; justify-content:center; margin-top:12px;">
<<button "Sleep">><<goto "DayEnd">><</button>>
</div>
</div><<set $locations = [
/* ── HAREM ───────────────────────────────────────────
Hidden until unlocked. Afterwards it is a normal location:
G1, G2 and any girl at corruption 75+ may roam here, with a
10% pull. Police never patrol it, no faction may base here,
and it is never a domination goal.
──────────────────────────────────────────────────── */
{
name: "Harem Mansion",
navLabel: "Harem Mansion",
section: "Harem",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: [],
harem: true, /* only G1/G2/75+ roam here; 10% draw */
noFaction: true, /* no faction may claim it as a base */
noGoal: true, /* not a domination target */
noPolice: true /* police never patrol it */
},
/* ── RESIDENTIAL ─────────────────────────────────── */
{
name: "House",
navLabel: "House",
/* Was its own one-entry "Home" section, which put a header above a
single row. It belongs with the other homes. */
section: "Residential",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: true,
pillars: ["emily", "jewelz", "elsa"]
},
{
name: "Neighbor's House",
navLabel: "Neighbor's House",
section: "Residential",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["laila", "demi"]
},
{
name: "Cousin's House",
navLabel: "Cousin's House",
section: "Residential",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["lana", "kylie"]
},
{
name: "Eva's House",
navLabel: "Eva's House",
section: "Residential",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["eva", "alina", "harmony"]
},
{
name: "Aria's House",
navLabel: "Aria's House",
section: "Residential",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["aria", "anya"]
},
{
name: "Mansion",
navLabel: "Mansion",
section: "Residential",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["luna", "casey", "haley"]
},
{
name: "Godmother's House",
navLabel: "Godmother's House",
section: "Residential",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["melissa", "vina"]
},
/* ── DORMS ────────────────────────────────────────── */
{
name: "$name's Dorm",
navLabel: "$name's Dorm",
section: "Dorms",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: true,
pillars: ["claire", "karlee", "scarlet"]
},
{
name: "Marie's Dorm",
navLabel: "Marie's Dorm",
section: "Dorms",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["blake", "marie", "myra"]
},
{
name: "Dormitory Hall",
navLabel: "Dormitory Hall",
section: "Dorms",
trait: "transient",
weekdays: true,
weekends: true,
unlocked: true,
pillars: [],
alwaysUnsafe: true
},
{
name: "Sorority House",
navLabel: "Sorority House",
section: "Dorms",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: true,
pillars: ["nancy"]
},
/* ── SCHOOL ───────────────────────────────────────── */
{
name: "School Hallway",
navLabel: "School Hallway",
section: "School",
trait: "transient",
weekdays: true,
weekends: false,
unlocked: true,
pillars: [],
alwaysUnsafe: true
},
{
name: "School Rooftop",
navLabel: "School Rooftop",
section: "School",
trait: "outdoor",
weekdays: true,
weekends: false,
unlocked: false,
pillars: [],
alwaysUnsafe: true
},
{
name: "Chanel's Class",
navLabel: "Chanel's Class",
section: "School",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: true,
pillars: ["chanel"]
},
{
name: "Amber's Class",
navLabel: "Amber's Class",
section: "School",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["amber"]
},
{
name: "Adriana's Class",
navLabel: "Adriana's Class",
section: "School",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["adriana"]
},
{
name: "Mia's Class",
navLabel: "Mia's Class",
section: "School",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["mia"]
},
{
name: "Veruca's Class",
navLabel: "Veruca's Class",
section: "School",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["veruca"]
},
{
name: "Staff Room",
navLabel: "Staff Room",
section: "School",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["anya", "mia", "veruca", "aidra", "chanel", "amber", "adriana"]
},
{
name: "Detention Room",
navLabel: "Detention Room",
section: "School",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["veruca", "mia"]
},
{
name: "Student Council",
navLabel: "Student Council",
section: "School",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["gabbie", "adria", "jade"]
},
{
name: "Library",
navLabel: "Library",
section: "School",
trait: "academic",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["caprice", "shazia"]
},
{
name: "Cafeteria",
navLabel: "Cafeteria",
section: "School",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["gina", "christie"]
},
{
name: "Cheerleader Track",
navLabel: "Cheerleader Track",
section: "School",
trait: "outdoor",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["isabella", "lacy", "athena"]
},
{
name: "School Pool",
navLabel: "School Pool",
section: "School",
trait: "outdoor",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["aidra", "ariana", "harley"]
},
/* ── CITY ─────────────────────────────────────────── */
{
name: "Gym",
navLabel: "Gym",
section: "City",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["alison", "abella", "leah"]
},
{
name: "Town Square",
navLabel: "Town Square",
section: "City",
trait: "transient",
weekdays: true,
weekends: true,
unlocked: false,
pillars: [],
alwaysUnsafe: true
},
{
name: "Restaurant",
navLabel: "Restaurant",
section: "City",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["kendra"]
},
{
name: "Hotel",
navLabel: "Hotel",
section: "City",
/* Rooms behind closed doors, not a thoroughfare. Intimate also takes
it out of the wildcard roaming pool, which was the real cause of
the crowding: four girls anchor here (Caitlyn and Stella work the
place, Autumn and Momo are long-stay guests) AND anyone could be
dropped here at random on top of that. */
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["caitlyn", "stella"]
},
{
name: "Office",
navLabel: "Office",
section: "City",
trait: "intimate",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["megan"]
},
{
name: "Park",
navLabel: "Park",
section: "City",
trait: "outdoor",
weekdays: true,
weekends: true,
unlocked: false,
pillars: [],
alwaysUnsafe: true
},
{
name: "Beach",
navLabel: "Beach",
section: "City",
trait: "outdoor",
weekdays: true,
weekends: true,
unlocked: false,
pillars: [],
alwaysUnsafe: true
},
/* ── MALL ────────────────────────────────── */
{
name: "Department Store",
navLabel: "Department Store",
section: "Mall",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["kali"]
},
{
name: "Arcade",
navLabel: "Arcade",
section: "Mall",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["natalia"]
},
{
name: "Spa",
navLabel: "Spa",
section: "Mall",
trait: "intimate",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["nikki"]
},
{
name: "Electronics Store",
navLabel: "Electronics",
section: "Mall",
trait: "transient",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["kate"]
},
{
name: "Real Estate",
navLabel: "Real Estate",
section: "Mall",
trait: "academic",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["quinn", "kenna"]
},
{
name: "Clothing Store",
navLabel: "Clothing Store",
section: "Mall",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["skylar"]
},
/* ── ENTERTAINMENT ────────────────────────────────── */
{
name: "Club",
navLabel: "Club",
section: "Entertainment",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["lexi", "leda"]
},
{
name: "Cinema",
navLabel: "Cinema",
section: "Entertainment",
trait: "socialHub",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["may"]
},
/* ── GOVERNMENT ───────────────────────────────────── */
{
name: "Police Station",
navLabel: "Police Station",
section: "Government",
trait: "critical",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["angel", "jane", "ember"]
},
{
name: "Courthouse",
navLabel: "Courthouse",
section: "Government",
trait: "critical",
weekdays: true,
weekends: false,
unlocked: false,
pillars: ["jessa"]
},
{
name: "Town Hall",
navLabel: "Town Hall",
section: "Government",
trait: "critical",
weekdays: true,
weekends: true,
unlocked: false,
pillars: ["nicole"]
}
]>><div style="background:#0a0014; border:2px solid #440088; padding:20px; border-radius:8px;">
<h1 style="color:#cc44ff; text-align:center;">⚗ THE LAB</h1>
<p style="color:#888; text-align:center; font-style:italic;">Government containment facility. Not yet accessible to the player.</p>
<p style="color:#aaa;">Infected individuals detained here undergo daily decontamination, losing 10 corruption per day until fully cleared and released.</p>
<<set _labChars = $roster.filter(id => State.variables[id] && State.variables[id].arrested)>>
<<if _labChars.length > 0>>
<h3 style="color:#cc44ff;">Currently Detained:</h3>
<ul>
<<for _labId range _labChars>>
<<set _lc = State.variables[_labId]>>
<li style="color:#cc88ff; margin:6px 0;">
<strong><<print _lc.name>></strong> — Corruption: <<print _lc.corr>>%
<span style="color:#666;">(losing 10/day)</span>
</li>
<</for>>
</ul>
<<else>>
<p style="color:#555; font-style:italic;">No subjects currently detained.</p>
<</if>>
</div>
<div style="margin-top:20px;">
<<back>>
</div>[[Go Back to the Hub|TownHub]]
<<nobr>>
<<if !$factionDirectiveMode>><<set $factionDirectiveMode = null>><</if>>
<<if !$factionDirectiveId>><<set $factionDirectiveId = null>><</if>>
<<set _visible = $factions.filter(f => window.getFactionVisibility(f) > 0)>>
<<set _domCount = _visible.filter(f => f.stance is "dominated").length>>
<<set _enthCount = _visible.filter(f => f.stance is "enthralled").length>>
<<if $factions.length === 0>>
<div style="text-align:center; color:#666; margin:40px 0;"><p>No factions have formed yet.</p><p style="font-size:0.9em;">Connected girls who spend time together may organise into groups.</p></div>
<<else>>
<div id="fx-root">
<style>
#fx-root { max-width:1040px; margin:0 auto; font-size:1.06em; }
#fx-root .fx-btn button { width:auto !important; display:inline-block !important; margin:0 !important; padding:4px 12px !important; font-size:0.92em !important; line-height:1.35 !important; white-space:nowrap; border-radius:4px; background:#1a1a1a; color:#ddd; border:1px solid #3a2a4a; cursor:pointer; }
#fx-root .fx-btn button:hover { background:#9c27b0; color:#fff; border-color:#d05ce3; }
#fx-root .fx-card { background:#0e0e0e; border:1px solid #262626; border-radius:7px; padding:11px 14px; margin-bottom:10px; }
#fx-root .fx-row { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
#fx-root .fx-mem { display:flex; flex-wrap:wrap; gap:7px; margin-top:9px; }
#fx-root .fx-chip { display:flex; align-items:center; gap:8px; background:#141414; border:1px solid #262626; border-radius:6px; padding:3px 12px 3px 3px; }
#fx-root .fx-face { width:64px; height:96px; border-radius:5px; background-size:cover; background-position:center top; flex:none; }
#fx-root .fx-active { margin-top:9px; background:#12001a; border-left:3px solid #9c27b0; border-radius:0 5px 5px 0; padding:7px 11px; }
#fx-root .fx-dir { display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-top:9px; padding-top:8px; border-top:1px solid #1f0f1f; }
#fx-root .fx-help { position:relative; display:inline-flex; align-items:center; justify-content:center; width:20px; height:20px; border-radius:50%; border:1px solid #4a3a5a; color:#8a7a9a; font-size:0.8em; font-weight:bold; cursor:help; user-select:none; flex:none; }
#fx-root .fx-help:hover { border-color:#bd59ff; color:#bd59ff; }
#fx-root .fx-tip { display:none; position:absolute; bottom:calc(100% + 8px); left:50%; transform:translateX(-50%); width:300px; background:#14081c; border:1px solid #6a0dad; border-radius:6px; padding:10px 12px; font-size:1.0em; font-weight:normal; color:#c5c5c5; line-height:1.5; text-align:left; white-space:normal; z-index:99; box-shadow:0 3px 14px rgba(0,0,0,0.88); pointer-events:none; }
#fx-root .fx-tip::after { content:""; position:absolute; top:100%; left:50%; margin-left:-5px; border:5px solid transparent; border-top-color:#6a0dad; }
#fx-root .fx-help:hover .fx-tip { display:block; }
#fx-root .fx-bar { width:74px; background:#1e1e1e; height:8px; border-radius:4px; overflow:hidden; }
</style>
<div style="display:flex; justify-content:space-between; align-items:baseline; border-bottom:1px solid #2a1a3a; padding-bottom:5px; margin-bottom:8px;"><h1 style="margin:0; color:#bd59ff; font-size:1.5em;">Faction Network</h1><span style="color:#666; font-size:0.92em;"><<print _visible.length>> known<<if _enthCount > 0>> · <span style="color:#ff8844;"><<print _enthCount>> enthralled</span><</if>><<if _domCount > 0>> · <span style="color:#ff44ff;"><<print _domCount>> dominated</span><</if>></span></div>
<<if $territoryConflicts.length > 0>>
<div style="background:#1a1000; border-left:3px solid #ffcc00; border-radius:0 4px 4px 0; padding:4px 9px; margin-bottom:8px; font-size:0.82em;"><span style="color:#ffcc00; font-weight:bold;">⚔</span> <<for _tc range $territoryConflicts>><<set _tcf1 = $factions.find(f => f.id === _tc.challengerId)>><<set _tcf2 = $factions.find(f => f.id === _tc.defenderId)>><<if _tcf1 and _tcf2>><span style="color:#ccc;"><b style="color:#ffdd88;"><<print _tcf1.name>></b> vs <b style="color:#ffdd88;"><<print _tcf2.name>></b> @ <<print _tc.loc>> · <span style="color:#ff8844;"><<print Math.max(0, 7 - ($day - _tc.startDay))>>d</span></span> <</if>><</for>></div>
<</if>>
<<if $factionDirectiveMsg>>
<div style="background:#12001a; border-left:3px solid #6a0dad; border-radius:0 4px 4px 0; padding:5px 9px; margin-bottom:8px; font-size:0.85em; color:#ddb3ff;"><<print $factionDirectiveMsg>></div>
<<set $factionDirectiveMsg = "">>
<</if>>
<div id="faction-list">
<<for _faction range $factions>>
<<set _f = _faction>>
<<set _vis = window.getFactionVisibility(_f)>>
<<if _vis === 0>><<continue>><</if>>
<<capture _f>>
<<set _stanceColor = _f.stance is "dominated" ? "#ff44ff" : _f.stance is "enthralled" ? "#ff8844" : _f.stance is "receptive" ? "#44ff88" : _f.stance is "uneasy" ? "#ffcc00" : "#555">>
<<set _stanceLabel = _f.stance is "dominated" ? "DOMINATED" : _f.stance is "enthralled" ? "ENTHRALLED" : _f.stance is "receptive" ? "RECEPTIVE" : _f.stance is "uneasy" ? "UNEASY" : "NEUTRAL">>
<<set _stab = _f.stability || 50>>
<<set _stabColor = _stab >= 70 ? "#44ff88" : _stab >= 40 ? "#ffcc00" : "#ff4444">>
<<set _fid = _f.id>>
<<set _avail = window.getAvailableDirectives(_fid)>>
<<set _hasAnyUp = $upgrades and ($upgrades.factionDirectives1 or $upgrades.factionDirectives2 or $upgrades.factionDirectives3 or $upgrades.factionDirectives4)>>
<<set _tierCol = { 1:"#88aaff", 2:"#44cc88", 3:"#ffaa44", 4:"#ff5555" }>>
<div class="fx-card" @style="'border-left:3px solid ' + _stanceColor + ';'"><div class="fx-row"><span style="color:#bd59ff; font-weight:bold; font-size:1.2em;"><<print window.factionDisplayNameCap(_f)>></span><<if _vis < 2>><span style="font-size:0.74em; color:#6a6a7a; font-style:italic;">partly known</span><</if>><span @style="'font-size:0.72em; font-weight:bold; letter-spacing:0.07em; padding:2px 7px; border-radius:4px; border:1px solid ' + _stanceColor + '; color:' + _stanceColor"><<print _stanceLabel>></span><span style="flex:1;"></span><span style="font-size:0.82em; color:#777;">Corr</span><div class="fx-bar"><div @style="'width:' + _f.corruption + '%; height:100%; background:#9c27b0;'"></div></div><span style="font-size:0.86em; color:#bd59ff; min-width:34px; font-weight:bold;"><<print _f.corruption>>%</span><span style="font-size:0.82em; color:#777;">Stab</span><div class="fx-bar"><div @style="'width:' + _stab + '%; height:100%; background:' + _stabColor + ';'"></div></div><span @style="'font-size:0.86em; min-width:28px; font-weight:bold; color:' + _stabColor"><<print _stab>></span><span style="font-size:0.8em; color:#555;"><<if _f.homeLocation>>🏠 <<print _f.homeLocation>><<else>>no home<</if>><<if (_f.playerInfluence || 0) > 0>> · <span style="color:#8855aa;">infl <<print _f.playerInfluence>>%</span><</if>></span></div><div class="fx-mem"><<for _mid range _f.members>><<set _mc = State.variables[_mid]>><<capture _mid>><<if _mc and _mc.met>><div class="fx-chip" @title="_mc.name + ' — corr ' + _mc.corr + '%'" @style="'border-color:' + (_mid is _f.leader ? '#5a2a7a' : '#222') + ';'"><div class="fx-face" @style="'background-image:url(' + window.getPortraitPath(_mc.name) + ');'"></div><div style="display:flex; flex-direction:column; line-height:1.3; gap:1px;"><span @style="'font-size:0.96em; color:' + (_mid is _f.leader ? '#bd59ff' : '#ccc') + ';'"><<if _mid is _f.leader>>★<</if>><<print _mc.name>></span><span style="font-size:0.84em; color:#777;"><<print _mc.corr>>%<<if _mc.infected>> <span style="color:#9c27b0;">☣</span><</if>></span></div></div><<else>><div class="fx-chip" style="opacity:0.4;"><div class="fx-face" style="background:#1a1a1a; display:flex; align-items:center; justify-content:center; color:#444; font-size:1.6em;">?</div><span style="font-size:0.96em; color:#555;">unknown</span></div><</if>><</capture>><</for>></div><<if _f.directive>><<set _actDef = window.DIRECTIVE_DEFS[_f.directive.id]>><div class="fx-active"><div style="display:flex; align-items:baseline; gap:8px; flex-wrap:wrap;"><span style="font-size:0.72em; font-weight:bold; letter-spacing:0.08em; color:#7a5a8a;">ACTIVE</span><b style="color:#cc88ff; font-size:1.02em;">⚡ <<print _actDef ? _actDef.name : _f.directive.id>></b><<if _f.directive.daysLeft>><span style="font-size:0.84em; color:#ffaa44;"><<print _f.directive.daysLeft>> day<<if _f.directive.daysLeft isnot 1>>s<</if>> left</span><<else>><span style="font-size:0.84em; color:#666;">resolves tonight</span><</if>></div><<if _actDef and _actDef.desc>><div style="font-size:0.88em; color:#9a8aaa; margin-top:3px; line-height:1.45;"><<print _actDef.desc>></div><</if>></div><<else>><div style="margin-top:9px; font-size:0.86em; color:#4a4a4a; font-style:italic;">No directive active.</div><</if>><<if $orderedClashes and $orderedClashes.some(o => o.attackerId is _fid)>><<set _oc = $orderedClashes.find(o => o.attackerId is _fid)>><<set _ocT = $factions.find(f => f.id is _oc.defenderId)>><div class="fx-active" style="border-left-color:#ffcc00;"><span style="font-size:0.72em; font-weight:bold; letter-spacing:0.08em; color:#8a7a4a;">ORDERED</span> <b style="color:#ffcc00;">⚔ Clash</b><span style="font-size:0.84em; color:#666;"> · resolves tonight</span><div style="font-size:0.88em; color:#9a8a6a; margin-top:3px;">Moving against <b><<print _ocT ? window.factionDisplayName(_ocT) : "a rival">></b>.</div></div><</if>><<if _hasAnyUp and _avail.length > 0 and ($factionDirectiveId isnot _fid or !$factionDirectiveMode)>><div class="fx-dir"><span style="font-size:0.78em; color:#666; letter-spacing:0.08em; font-weight:bold;">DIRECTIVES</span><<for _d range _avail>><<capture _d _fid _tierCol>><span style="display:inline-flex; align-items:center; gap:3px;"><span @style="'font-size:0.7em; font-weight:bold; padding:2px 5px; border-radius:3px; border:1px solid ' + _tierCol[_d.tier] + '; color:' + _tierCol[_d.tier] + ';'">T<<print _d.tier>></span><span class="fx-btn"><<if _d.needsTarget>><<button _d.name>><<set $factionDirectiveMode = _d.id>><<set $factionDirectiveId = _fid>><<replace "#faction-list">><<include "Factions">><</replace>><</button>><<else>><<button _d.name>><<set _r = window.issueDirective(_fid, _d.id, null)>><<set $factionDirectiveMsg = _r.msg>><<set $factionDirectiveMode = null>><<set $factionDirectiveId = null>><<replace "#faction-list">><<include "Factions">><</replace>><</button>><</if>></span><span class="fx-help">?<span class="fx-tip"><b style="color:#cc88ff;"><<print _d.name>></b> <span style="color:#666;">· T<<print _d.tier>> · <<print _d.type is "instant" ? "instant" : (_d.duration || "?") + "d">></span><br><<print _d.desc>><<if _d.needsTarget>> <span style="color:#ff88ff;">Requires a target.</span><</if>></span></span></span><</capture>><</for>></div><</if>><<if _hasAnyUp and _avail.length === 0>><<set _nextStance = { "neutral":"uneasy", "uneasy":"receptive", "receptive":"enthralled", "enthralled":"dominated" }[_f.stance]>><div style="margin-top:8px; font-size:0.85em; color:#555; font-style:italic;">No directives<<if _nextStance>> — raise to <<print _nextStance.toUpperCase()>> or buy a higher Directives upgrade<<else>> — buy a higher Directives upgrade<</if>>.</div><</if>><<if $factionDirectiveId is _fid and $factionDirectiveMode>><<set _mode = $factionDirectiveMode>><<set _mDef = window.DIRECTIVE_DEFS[_mode]>><div style="background:#150015; border-radius:5px; padding:10px; margin-top:9px;"><div style="display:flex; justify-content:space-between; align-items:center; gap:8px; margin-bottom:5px;"><span style="font-size:0.96em; color:#cc88ff;"><<if _mode is "expelMember">>Expel who?<<elseif _mode is "betrayal">>Turn on who?<<elseif _mode is "mergeFaction">>Absorb which faction?<<elseif _mode is "startClash">>Clash with which faction?<<elseif _mode is "infiltrate">>Send which agent?<<elseif _mode is "infiltrateTarget">>Into which faction?<<else>><<print _mDef ? _mDef.name : _mode>><</if>></span><span class="fx-btn"><<button "✕">><<set $factionDirectiveMode = null>><<set $factionDirectiveId = null>><<replace "#faction-list">><<include "Factions">><</replace>><</button>></span></div><div style="display:flex; flex-wrap:wrap; gap:6px;"><<if _mode is "betrayal">><<set _bTargets = _f.members.filter(id => id isnot _f.leader and State.variables[id] and State.variables[id].met and !State.variables[id].captive and !State.variables[id].arrested)>><<if _bTargets.length === 0>><div style="font-size:0.94em; color:#555;">Nobody here can be taken.</div><<else>><<for _bid range _bTargets>><<set _bc = State.variables[_bid]>><<capture _bid _fid>><span class="fx-btn"><<button _bc.name>><<set _r = window.issueDirective(_fid, "betrayal", _bid)>><<set $factionDirectiveMsg = _r.msg>><<set $factionDirectiveMode = null>><<set $factionDirectiveId = null>><<replace "#faction-list">><<include "Factions">><</replace>><</button>></span><</capture>><</for>><</if>><<elseif _mode is "expelMember">><<for _eid range _f.members>><<if _eid isnot _f.leader>><<set _ec = State.variables[_eid]>><<capture _eid _fid>><span class="fx-btn"><<button _ec.name>><<set _r = window.issueDirective(_fid, "expelMember", _eid)>><<set $factionDirectiveMsg = _r.msg>><<set $factionDirectiveMode = null>><<set $factionDirectiveId = null>><<replace "#faction-list">><<include "Factions">><</replace>><</button>></span><</capture>><</if>><</for>><<elseif _mode is "mergeFaction" or _mode is "startClash">><<set _tgts = $factions.filter(f => f.id !== _fid and window.getFactionVisibility(f) > 0)>><<if _tgts.length === 0>><div style="font-size:0.94em; color:#555;">No eligible factions.</div><<else>><<for _tg range _tgts>><<capture _tg _fid _mode>><span class="fx-btn"><<button _tg.name>><<set _r = window.issueDirective(_fid, _mode, _tg.id)>><<set $factionDirectiveMsg = _r.msg>><<set $factionDirectiveMode = null>><<set $factionDirectiveId = null>><<replace "#faction-list">><<include "Factions">><</replace>><</button>></span><</capture>><</for>><</if>><<elseif _mode is "infiltrate">><<set _agents = _f.members.filter(id => State.variables[id] and State.variables[id].met and State.variables[id].corr >= 50 and !State.variables[id].captive and !State.variables[id].arrested)>><<if _agents.length === 0>><div style="font-size:0.94em; color:#555;">Nobody in this faction is at corr 50+.</div><<else>><<for _aid range _agents>><<set _ac = State.variables[_aid]>><<capture _aid _fid>><span class="fx-btn"><<button _ac.name>><<set $factionInfiltrateAgent = _aid>><<set $factionDirectiveMode = "infiltrateTarget">><<replace "#faction-list">><<include "Factions">><</replace>><</button>></span><</capture>><</for>><</if>><<elseif _mode is "infiltrateTarget">><<set _tgts2 = $factions.filter(f => f.id !== _fid and window.getFactionVisibility(f) > 0)>><<for _tg2 range _tgts2>><<capture _tg2 _fid>><span class="fx-btn"><<button _tg2.name>><<set _r = window.issueDirective(_fid, "infiltrate", $factionInfiltrateAgent, _tg2.id)>><<set $factionDirectiveMsg = _r.msg>><<set $factionDirectiveMode = null>><<set $factionDirectiveId = null>><<replace "#faction-list">><<include "Factions">><</replace>><</button>></span><</capture>><</for>><</if>></div></div><</if>></div>
<</capture>>
<</for>>
</div>
</div>
<</if>>
<</nobr>>
[[Go Back to the Hub|TownHub]]<<nobr>>
<<set _faction = $factions.find(f => f.id === $attendingParty)>>
<<if !_faction>><<goto "TownHub">><</if>>
<<set _leader = State.variables[_faction.leader]>>
<<set _stanceColors = {
"neutral": "#666",
"uneasy": "#88aaff",
"receptive": "#bd59ff",
"enthralled":"#ff88cc",
"dominated": "#ff4444"
}>>
<<set _stanceColor = _stanceColors[_faction.stance] || "#666">>
/* ── AUTO-INTRODUCE: one unmet contact-method member per party ── */
<<set _partyIntroTarget = null>>
<<set _partyIntroGiver = null>>
<<for _pid range _faction.members>>
<<set _pc = State.variables[_pid]>>
<<if !_pc.met and _pc.meetingMethod is "contact" and !_partyIntroTarget>>
<<for _cid range _pc.connections>>
<<set _cc = State.variables[_cid]>>
<<if _cc and _cc.met and _cc.corr >= 25 and _faction.members.includes(_cid)>>
<<if !_partyIntroGiver>>
<<set _partyIntroGiver = _cid>>
<<set _partyIntroTarget = _pid>>
<<set State.variables[_pid].met = true>>
<<run window.rollNewGoals()>>
<</if>>
<</if>>
<</for>>
<</if>>
<</for>>
<<set _partyResults = window.resolvePartyMingle($attendingParty)>>
<</nobr>>
/* ── HEADER ── */
<div style="text-align:center; margin-bottom:20px; border-bottom:2px solid #9c27b0; padding-bottom:12px;">
<div style="font-size:0.72em; text-transform:uppercase; letter-spacing:0.14em; color:#6a0dad; margin-bottom:4px;">Faction Party</div>
<h1 style="margin:0; color:#bd59ff;">🎉 <<print _faction.name>></h1>
<div style="margin-top:6px; display:flex; justify-content:center; align-items:center; gap:12px; flex-wrap:wrap; font-size:0.85em;">
<span style="color:#555;"><<print _faction.members.length>> members</span>
<span style="color:#555;">·</span>
<span @style="'color:' + _stanceColor + '; font-weight:bold; text-transform:uppercase; font-size:0.88em;'"><<print _faction.stance>></span>
<span style="color:#555;">·</span>
<span style="color:#555;">Stability: <span style="color:#ccc;"><<print _faction.stability>>%</span></span>
<span style="color:#555;">·</span>
<span style="color:#555;">Parasites: <span style="color:#bd59ff; font-weight:bold;">$parasite</span></span>
</div>
</div>
/* ── VIDEO ── */
<<set _corruptMembers = []>>
<<for _id range _faction.members>>
<<if State.variables[_id].corr >= 25>><<run _corruptMembers.push(_id)>><</if>>
<</for>>
<<if _corruptMembers.length > 0>>
<div style="background:#000; padding:10px; border:1px solid #333; border-radius:8px; margin-bottom:20px;">
<<GroupVideos _corruptMembers>>
</div>
<<else>>
<div style="text-align:center; color:#555; font-style:italic; margin-bottom:20px; padding:15px; background:#111; border-radius:6px;">
The atmosphere is innocent... for now.
</div>
<</if>>
/* ── MINGLE RESULTS ── */
<<if _partyResults.length > 0>>
<div style="background:#1a1a1a; border:1px solid #9c27b0; border-radius:6px; padding:12px; margin-bottom:20px;">
<strong style="color:#bd59ff; font-size:0.85em; text-transform:uppercase; display:block; margin-bottom:8px;">Party Events</strong>
<ul style="margin:0; padding-left:18px; color:#ccc; font-size:0.88em; line-height:1.7;">
<<for _msg range _partyResults>><li><<print _msg>></li><</for>>
</ul>
</div>
<</if>>
/* ── INTRODUCTION SCENE ── */
<<if _partyIntroTarget>>
<<set _mt = State.variables[_partyIntroTarget]>>
<<set _mi = State.variables[_partyIntroGiver]>>
<div style="background:#0d001a; border:1px solid #5a1a8a; border-radius:8px; padding:14px; margin-bottom:20px;">
<div style="color:#cc88ff; font-size:0.85em; font-weight:bold; text-transform:uppercase; margin-bottom:12px;">👋 New Introduction</div>
<div style="display:flex; gap:16px; justify-content:center; align-items:flex-end; margin-bottom:16px;">
<div style="text-align:center; flex:1; max-width:180px;">
<img @src="window.getEventImagePath(_mi.name)" style="width:100%; border-radius:6px; border:2px solid #9c27b0;">
<div style="color:#bd59ff; font-size:0.82em; margin-top:5px; font-weight:bold;"><<print _mi.name>></div>
</div>
<div style="color:#555; font-size:1.6em; padding-bottom:28px;">→</div>
<div style="text-align:center; flex:1; max-width:180px;">
<img @src="window.getEventImagePath(_mt.name)" style="width:100%; border-radius:6px; border:2px solid #555; filter:brightness(0.5);">
<div style="color:#555; font-size:0.82em; margin-top:5px;">???</div>
</div>
</div>
<p style="color:#ccc; font-size:0.9em;">The party is loud and warm. <<print _mi.name>> touches your arm and leans in close enough to be heard.</p>
<<speech _partyIntroGiver>>"There's someone here you should know. Come on."<</speech>>
<p style="color:#ccc; font-size:0.9em;">She leads you through the crowd.</p>
<<speech _partyIntroGiver>>"<<print _mt.name>>, this is $name. $name — <<print _mt.name>>."<</speech>>
<div style="display:flex; gap:16px; justify-content:center; align-items:flex-end; margin:16px 0 10px;">
<div style="text-align:center; flex:1; max-width:180px;">
<img @src="window.getEventImagePath(_mi.name)" style="width:100%; border-radius:6px; border:2px solid #9c27b0;">
<div style="color:#bd59ff; font-size:0.82em; margin-top:5px; font-weight:bold;"><<print _mi.name>></div>
</div>
<div style="color:#555; font-size:1.6em; padding-bottom:28px;">→</div>
<div style="text-align:center; flex:1; max-width:180px;">
<img @src="window.getEventImagePath(_mt.name)" style="width:100%; border-radius:6px; border:2px solid #bd59ff;">
<div style="color:#bd59ff; font-size:0.82em; margin-top:5px; font-weight:bold;"><<print _mt.name>></div>
</div>
</div>
<<if _mt.description>>
<div style="background:#111; border-left:3px solid #5a1a8a; padding:10px 14px; border-radius:0 4px 4px 0; color:#aaa; font-style:italic; font-size:0.85em; line-height:1.6; margin-top:8px;">
<<print _mt.description>>
</div>
<</if>>
<p style="color:#555; font-size:0.82em; text-align:center; margin-top:12px;">
You've met <strong style="color:#bd59ff;"><<print _mt.name>></strong>.
</p>
</div>
<</if>>
/* ── MEMBER GRID ── */
<div style="display:flex; flex-wrap:wrap; gap:10px; justify-content:flex-start; margin-bottom:20px;">
<<for _memberId range _faction.members>>
<<set _member = State.variables[_memberId]>>
<<capture _memberId>>
<<set _isLeader = _memberId is _faction.leader>>
<<set _memCap = window.getCorrCap ? window.getCorrCap(_memberId) : 25>>
<<set _atCap = _member.infected && _member.corr >= _memCap && _member.corr < 100>>
<div style="text-align:center; width:140px;">
<<if _member.met>>
<<set _img = window.getEventImagePath(_member.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; position:relative; border:2px solid ' + (_isLeader ? '#ffaa22' : _atCap ? '#bd59ff' : 'transparent') + ';'">
<div class="loc-bar-container">
<div class="loc-bar-fill" @style="'width:' + _member.corr + '%'"></div>
</div>
<<if _atCap>>
<div style="position:absolute; top:3px; right:3px; background:#bd59ff; color:#fff; font-size:0.58em; font-weight:bold; padding:2px 4px; border-radius:3px;">CAP</div>
<</if>>
<<if _isLeader>>
<div style="position:absolute; top:3px; left:3px; background:#ffaa22; color:#000; font-size:0.58em; font-weight:bold; padding:2px 4px; border-radius:3px;">LEADER</div>
<</if>>
</div>
<div style="font-size:0.85em; font-weight:bold; color:#ccc; margin-top:4px;"><<charLink _memberId>></div>
<<elseif $upgrades && $upgrades.revealPortraits>>
<<set _img = window.getPortraitPath(_member.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; filter:grayscale(1); opacity:0.3;'"></div>
<div style="font-size:0.85em; color:#333; margin-top:4px;">???</div>
<<else>>
<div style="width:140px; height:210px; background:#111; border-radius:6px; display:flex; align-items:center; justify-content:center; border:1px solid #222;">
<span style="font-size:3em; color:#444;">?</span>
</div>
<div style="font-size:0.85em; color:#444; margin-top:4px;">???</div>
<</if>>
<div style="font-size:0.75em; margin-top:2px;">
<<if _member.breed>><span style="color:#ff5959;">♥ Bred</span>
<<elseif _member.infected>><span style="color:#bd59ff;">☣ Infected</span>
<<else>><span style="color:#444;">Healthy</span>
<</if>>
</div>
</div>
<</capture>>
<</for>>
</div>
/* ── BRED CHECK ── */
<<set _newlyBred = []>>
<<for _bid range _faction.members>>
<<set _bc = State.variables[_bid]>>
/* Breeding: corruption 75 or more. The old rule ALSO demanded she be at her
personal cap, which made breeding impossible for most of the late game —
once you bought Universal Threshold III (or broke her cap) the ceiling was
100, so a devoted girl at 75, 80 or 90 could never be bred. Only a girl
sitting exactly at her cap qualified, which is why it fired sometimes and
not others. 75 is the Devoted threshold and is the intended gate. */
<<if _bc.corr >= 75 and !_bc.breed>>
<<set State.variables[_bid].breed = true>>
<<run _newlyBred.push(_bc.name)>>
<</if>>
<</for>>
<<if _newlyBred.length > 0>>
<div style="background:#1a0010; border:1px solid #ff5959; border-radius:6px; padding:12px; margin-bottom:20px; text-align:center;">
<strong style="color:#ff5959; font-size:0.92em; display:block; margin-bottom:6px;">♥ Bred This Party</strong>
<<for _bn range _newlyBred>>
<div style="color:#ff8888; font-size:0.88em; margin-bottom:2px;"><<print _bn>> has been bred.</div>
<</for>>
</div>
<</if>>
<div style="margin-top:24px; text-align:center; display:flex; gap:12px; justify-content:center;">
<<button "Return to Town">>
<<set $attendingParty = null>>
<<set $pendingParties = []>>
<<set $partyMeetTarget = "">>
<<set $partyMeetIntroducer = "">>
<<goto "TownHub">>
<</button>>
<<button "Sleep">>
<<set $attendingParty = null>>
<<set $pendingParties = []>>
<<set $partyMeetTarget = "">>
<<set $partyMeetIntroducer = "">>
<<goto "DayEnd">>
<</button>>
</div><<nobr>>
<<set _f1 = $factions.find(f => f.id === $attendingClash.id1)>>
<<set _f2 = $factions.find(f => f.id === $attendingClash.id2)>>
<<if !_f1 or !_f2>><<goto "TownHub">><</if>>
<<set _corrCap = window.getCorrCap ? window.getCorrCap() : 25>>
<<set _pool = [...new Set(_f1.members.concat(_f2.members))]>>
<<set _attendees = _pool.sort(() => 0.5 - Math.random()).slice(0, 7)>>
<<set _clashEvent = "the clash between " + window.factionDisplayName(_f1) + " and " + window.factionDisplayName(_f2)>>
<<set _results = window.resolvePartyMingle(_attendees, "Faction Clash", _clashEvent)>>
<<set _corrupt = []>>
<<for _id range _attendees>>
<<if State.variables[_id].corr >= 25>><<run _corrupt.push(_id)>><</if>>
<</for>>
<<set _isTerritory = $attendingClash.type is "territory">>
<<set _tConflict = null>>
<<set _winner = null>>
<<set _loser = null>>
<<set _territory = "">>
<<if _isTerritory>>
<<set _tConflict = $territoryConflicts
? $territoryConflicts.find(c =>
(c.challengerId === $attendingClash.id1 && c.defenderId === $attendingClash.id2) ||
(c.challengerId === $attendingClash.id2 && c.defenderId === $attendingClash.id1))
: null>>
<<if _tConflict>><<set _territory = _tConflict.loc>><</if>>
<<set _winner = _f1>>
<<set _loser = _f2>>
<</if>>
<<set _stanceColors = {
"neutral": "#666",
"uneasy": "#88aaff",
"receptive": "#bd59ff",
"enthralled":"#ff88cc",
"dominated": "#ff4444"
}>>
<</nobr>>
/* ── HEADER ── */
<div style="text-align:center; margin-bottom:20px; border-bottom:2px solid #ffcc00; padding-bottom:12px;">
<div style="font-size:0.72em; text-transform:uppercase; letter-spacing:0.14em; color:#aa8800; margin-bottom:4px;">Faction Clash</div>
<h1 style="margin:0; color:#ffcc00; font-size:1.5em;">⚡ <<print _f1.name>> vs <<print _f2.name>></h1>
</div>
/* ── FACTION COMPARISON ── */
<div style="display:grid; grid-template-columns:1fr auto 1fr; gap:10px; align-items:center; margin-bottom:20px;">
<div style="background:#0a0a14; border:1px solid #ffcc00; border-radius:8px; padding:12px; text-align:center;">
<div style="font-weight:bold; color:#ffdd88; font-size:0.95em; margin-bottom:6px;"><<print _f1.name>></div>
<<set _l1 = State.variables[_f1.leader]>>
<<if _l1 and _l1.met>>
<img @src="window.getPortraitPath(_l1.name)" style="width:60px; height:90px; border-radius:6px; border:2px solid #ffcc00; object-fit:cover; object-position:top; display:block; margin:0 auto 6px;">
<</if>>
<div style="font-size:0.75em; color:#888; margin-bottom:3px;"><<print _f1.members.length>> members</div>
<div @style="'font-size:0.75em; font-weight:bold; text-transform:uppercase; color:' + (_stanceColors[_f1.stance] || '#666') + ';'"><<print _f1.stance>></div>
<div style="font-size:0.72em; color:#555; margin-top:3px;">Stability: <<print _f1.stability>>%</div>
<div style="font-size:0.72em; color:#555;">Corruption: <<print _f1.corruption>>%</div>
</div>
<div style="text-align:center; color:#ffcc00; font-size:1.8em; font-weight:bold;">VS</div>
<div style="background:#0a0a14; border:1px solid #888; border-radius:8px; padding:12px; text-align:center;">
<div style="font-weight:bold; color:#ccc; font-size:0.95em; margin-bottom:6px;"><<print _f2.name>></div>
<<set _l2 = State.variables[_f2.leader]>>
<<if _l2 and _l2.met>>
<img @src="window.getPortraitPath(_l2.name)" style="width:60px; height:90px; border-radius:6px; border:2px solid #888; object-fit:cover; object-position:top; display:block; margin:0 auto 6px;">
<</if>>
<div style="font-size:0.75em; color:#888; margin-bottom:3px;"><<print _f2.members.length>> members</div>
<div @style="'font-size:0.75em; font-weight:bold; text-transform:uppercase; color:' + (_stanceColors[_f2.stance] || '#666') + ';'"><<print _f2.stance>></div>
<div style="font-size:0.72em; color:#555; margin-top:3px;">Stability: <<print _f2.stability>>%</div>
<div style="font-size:0.72em; color:#555;">Corruption: <<print _f2.corruption>>%</div>
</div>
</div>
/* ── TERRITORY OUTCOME ── */
<<if _isTerritory>>
<div style="background:#1a1000; border:2px solid #ffaa44; border-radius:8px; padding:14px; margin-bottom:20px;">
<div style="color:#ffaa44; font-weight:bold; margin-bottom:8px; font-size:0.95em;">
⚔ Territory Dispute<<if _territory>> — <span style="color:#ffdd88;"><<print _territory>></span><</if>>
</div>
<div style="color:#ccc; font-size:0.88em; margin-bottom:12px;">
<<if _territory>>
<b style="color:#ffdd88;"><<print _f1.name>></b> and <b style="color:#aaa;"><<print _f2.name>></b> have both been anchoring at <b><<print _territory>></b>. Today it gets settled.
<<else>>
Two factions have been fighting over the same ground.
<</if>>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:10px;">
<div style="background:#1a1500; border:1px solid #ffcc00; border-radius:6px; padding:10px; text-align:center;">
<div style="color:#44ff88; font-weight:bold; font-size:0.82em; margin-bottom:4px;">✓ WINNER</div>
<div style="color:#ffdd88; font-weight:bold;"><<print _winner.name>></div>
<div style="color:#666; font-size:0.78em; margin-top:4px;">Controls <<print _territory || "the area">> · Stability +10</div>
</div>
<div style="background:#0d0d0d; border:1px solid #444; border-radius:6px; padding:10px; text-align:center;">
<div style="color:#ff4444; font-weight:bold; font-size:0.82em; margin-bottom:4px;">✗ DISPLACED</div>
<div style="color:#aaa; font-weight:bold;"><<print _loser.name>></div>
<div style="color:#666; font-size:0.78em; margin-top:4px;">Lost territory · Stability −15</div>
</div>
</div>
</div>
<</if>>
/* ── VIDEO ── */
<<if _corrupt.length > 0>>
<div style="background:#000; padding:10px; border:1px solid #ffcc00; border-radius:8px; margin-bottom:20px;">
<<GroupVideos _corrupt>>
</div>
<</if>>
/* ── RESULTS ── */
<<if _results.length > 0>>
<div style="background:#1a1000; border:1px solid #ffcc00; border-radius:6px; padding:12px; margin-bottom:20px;">
<strong style="color:#ffcc00; font-size:0.85em; text-transform:uppercase; display:block; margin-bottom:8px;">Actions Taken</strong>
<ul style="margin:0; padding-left:18px; color:#ccc; font-size:0.88em; line-height:1.7;">
<<for _r range _results>><li><<print _r>></li><</for>>
</ul>
</div>
<</if>>
/* ── ATTENDEES ── */
<div style="display:flex; flex-wrap:wrap; gap:10px; justify-content:flex-start; margin-bottom:20px;">
<<for _memberId range _attendees>>
<<set _member = State.variables[_memberId]>>
<<capture _memberId>>
<<set _inF1 = _f1.members.includes(_memberId)>>
<<set _borderColor = _inF1 ? "#ffcc00" : "#888">>
<<set _fLabel = _inF1 ? _f1.name : _f2.name>>
<<set _isLeader = _memberId is _f1.leader or _memberId is _f2.leader>>
<<set _atCap = _member.infected && _member.corr >= _corrCap && _member.corr < 100>>
<div style="text-align:center; width:140px;">
<<if _member.met>>
<<set _img = window.getEventImagePath(_member.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; position:relative; border:2px solid ' + (_atCap ? '#bd59ff' : _borderColor) + ';'">
<div class="loc-bar-container">
<div class="loc-bar-fill" @style="'width:' + _member.corr + '%'"></div>
</div>
<<if _atCap>>
<div style="position:absolute; top:3px; right:3px; background:#bd59ff; color:#fff; font-size:0.58em; font-weight:bold; padding:2px 4px; border-radius:3px;">CAP</div>
<</if>>
<<if _isLeader>>
<div style="position:absolute; top:3px; left:3px; background:#ffaa22; color:#000; font-size:0.58em; font-weight:bold; padding:2px 4px; border-radius:3px;">LEADER</div>
<</if>>
</div>
<div style="font-size:0.85em; font-weight:bold; color:#ccc; margin-top:4px;"><<charLink _memberId>></div>
<<elseif $upgrades && $upgrades.revealPortraits>>
<<set _img = window.getPortraitPath(_member.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; filter:grayscale(1); opacity:0.3; border:2px solid ' + _borderColor + ';'"></div>
<div style="font-size:0.85em; color:#333; margin-top:4px;">???</div>
<<else>>
<div @style="'width:140px; height:210px; background:#111; border-radius:6px; display:flex; align-items:center; justify-content:center; border:2px solid ' + _borderColor + ';'">
<span style="font-size:3em; color:#444;">?</span>
</div>
<div style="font-size:0.85em; color:#444; margin-top:4px;">???</div>
<</if>>
<div style="font-size:0.72em; margin-top:2px;" @style="'color:' + _borderColor + '; opacity:0.8;'"><<print _fLabel>></div>
<div style="font-size:0.75em; margin-top:1px;">
<<if _member.breed>><span style="color:#ff5959;">♥ Bred</span>
<<elseif _member.infected>><span style="color:#bd59ff;">☣ Infected</span>
<<else>><span style="color:#444;">Healthy</span>
<</if>>
</div>
</div>
<</capture>>
<</for>>
</div>
/* ── BRED CHECK ── */
<<set _newlyBred = []>>
<<for _bid range _attendees>>
<<set _bc = State.variables[_bid]>>
/* Breeding: corruption 75 or more. The old rule ALSO demanded she be at her
personal cap, which made breeding impossible for most of the late game —
once you bought Universal Threshold III (or broke her cap) the ceiling was
100, so a devoted girl at 75, 80 or 90 could never be bred. Only a girl
sitting exactly at her cap qualified, which is why it fired sometimes and
not others. 75 is the Devoted threshold and is the intended gate. */
<<if _bc.corr >= 75 and !_bc.breed>>
<<set State.variables[_bid].breed = true>>
<<run _newlyBred.push(_bc.name)>>
<</if>>
<</for>>
<<if _newlyBred.length > 0>>
<div style="background:#1a0010; border:1px solid #ff5959; border-radius:6px; padding:12px; margin-bottom:20px; text-align:center;">
<strong style="color:#ff5959; font-size:0.92em; display:block; margin-bottom:6px;">♥ Bred This Clash</strong>
<<for _bn range _newlyBred>>
<div style="color:#ff8888; font-size:0.88em; margin-bottom:2px;"><<print _bn>> has been bred.</div>
<</for>>
</div>
<</if>>
<div style="text-align:center; margin-top:24px; display:flex; gap:12px; justify-content:center;">
<<button "Return to Town">>
<<set $attendingClash = null>>
<<goto "TownHub">>
<</button>>
<<button "Sleep">>
<<set $attendingClash = null>>
<<goto "DayEnd">>
<</button>>
</div><<nobr>>
<<set _room = $currentLocation>>
<<set _profKey = "">>
<<if _room is "Chanel's Class">> <<set _profKey = "Chanel">>
<<elseif _room is "Amber's Class">> <<set _profKey = "Amber">>
<<elseif _room is "Adriana's Class">> <<set _profKey = "Adriana">>
<<elseif _room is "Mia's Class">> <<set _profKey = "Mia">>
<<elseif _room is "Veruca's Class">> <<set _profKey = "Veruca">>
<<elseif _room is "School Pool">> <<set _profKey = "Aidra">>
<</if>>
<<set _attendees = []>>
<<set _profId = _profKey.toLowerCase()>>
<<run _attendees.push(_profId)>>
<<set _students = $classRosters[_profKey]>>
<<set _attendanceRate = 0.6 + (Math.random() * 0.4)>>
<<set _presentCount = Math.floor(_students.length * _attendanceRate)>>
<<set _shuffledStudents = _students.sort(() => 0.5 - Math.random()).slice(0, _presentCount)>>
<<for _s range _shuffledStudents>>
<<if !State.variables[_s].arrested>><<run _attendees.push(_s)>><</if>>
<</for>>
<<set _results = window.resolvePartyMingle(_attendees, $currentLocation, "a lecture in " + $currentLocation, "activity")>>
<<set _corrupt = []>>
<<for _id range _attendees>>
<<if State.variables[_id].corr >= 25>><<run _corrupt.push(_id)>><</if>>
<</for>>
<</nobr>>
<div style="text-align:center; border-bottom:2px solid #9c27b0; padding-bottom:10px; margin-bottom:20px;">
<h1 style="margin:0; color:#bd59ff;">📖 <<print _profKey>>'s Class</h1>
<div style="color:#aaa; font-size:0.88em; margin-top:4px;">
Teacher: <strong><<print State.variables[_profId].name>></strong>
· <<print _attendees.length - 1>> students present
</div>
</div>
<<if _corrupt.length > 0>>
<div style="background:#000; padding:10px; border:1px solid #555; border-radius:8px; margin-bottom:20px;">
<<GroupVideos _corrupt>>
</div>
<<else>>
<div style="text-align:center; padding:20px; color:#666; font-style:italic; background:#111; border-radius:6px; margin-bottom:20px;">
The class listens attentively. No corruption visible... yet.
</div>
<</if>>
<<if _results.length > 0>>
<div style="background:#1a1a1a; border:1px solid #9c27b0; padding:12px; border-radius:6px; margin-bottom:20px;">
<strong style="color:#bd59ff; display:block; margin-bottom:6px;">Lecture Events:</strong>
<ul style="color:#ccc; margin:0; padding-left:18px; font-size:0.9em;">
<<for _r range _results>><li><<print _r>></li><</for>>
</ul>
</div>
<</if>>
<div style="display:flex; flex-wrap:wrap; gap:10px; justify-content:flex-start; margin-bottom:20px;">
<<for _id range _attendees>>
<<set _char = State.variables[_id]>>
<<capture _id>>
<<set _girlCap = window.getCorrCap ? window.getCorrCap(_id) : 25>>
<<set _atCap = _char.infected && _char.corr >= _girlCap && _char.corr < 100>>
<<set _isProf = _id is _profId>>
<div style="text-align:center; width:140px;">
<<if _char.met>>
<<set _img = window.getEventImagePath(_char.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; position:relative; border:2px solid ' + (_isProf ? '#ffaa22' : _atCap ? '#bd59ff' : 'transparent') + ';'">
<div class="loc-bar-container">
<div class="loc-bar-fill" @style="'width:' + _char.corr + '%'"></div>
</div>
<<if _atCap and !_isProf>>
<div style="position:absolute; top:3px; right:3px; background:#bd59ff; color:#fff; font-size:0.58em; font-weight:bold; padding:2px 4px; border-radius:3px;">CAP</div>
<</if>>
</div>
<div style="font-size:0.85em; font-weight:bold; color:#ccc; margin-top:4px;"><<charLink _id>></div>
<<if _isProf>>
<div style="font-size:0.72em; color:#ffaa22; font-weight:bold; margin-top:2px;">TEACHER</div>
<<else>>
<div style="font-size:0.72em; margin-top:2px;">
<<if _char.breed>><span style="color:#ff5959;">♥ Bred</span>
<<elseif _char.infected>><span style="color:#bd59ff;">☣ Infected</span>
<<else>><span style="color:#444;">Healthy</span>
<</if>>
</div>
<</if>>
<<elseif $upgrades && $upgrades.revealPortraits>>
<<set _img = window.getPortraitPath(_char.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; filter:grayscale(1); opacity:0.3;'"></div>
<div style="font-size:0.85em; color:#333; margin-top:4px;">???</div>
<div style="font-size:0.72em; color:#222; margin-top:2px;">Unknown</div>
<<else>>
<div style="width:140px; height:210px; background:#111; border-radius:6px; display:flex; align-items:center; justify-content:center; border:1px solid #222;">
<span style="font-size:3em; color:#444;">?</span>
</div>
<div style="font-size:0.85em; color:#444; margin-top:4px;">???</div>
<</if>>
</div>
<</capture>>
<</for>>
</div>
/* A lecture is the day, the same as an Activity or a group session. Offering
a free walk back to the hub let the player run it and then still do
everything else. Activity already ends on Sleep alone; this now matches. */
<div style="text-align:center; margin-top:24px; display:flex; gap:12px; justify-content:center; flex-wrap:wrap;">
<<button "Sleep">><<goto "DayEnd">><</button>>
</div>/*
WIDGET: InfectSuspicion
Usage: <<InfectSuspicion "charId" "LocationName">>
*/
<<widget "InfectSuspicion">><<nobr>>
<<set _targetId to _args[0]>>
<<set _locName to _args[1] || "Unknown">>
<<set _tChar to State.variables[_targetId]>>
/* 1. Base Gain based on Trait */
<<set _gain to 5>>
<<if _tChar.trait is "authority">><<set _gain to 20>>
<<elseif _tChar.trait is "flashpoint">><<set _gain to 12>>
<<elseif _tChar.trait is "influential">><<set _gain to 8>>
<</if>>
/* 2. Authority Witness Check */
<<set _witnessed to window.isAuthorityPresent(_locName)>>
<<if _witnessed>>
<<set _gain += 15>>
<</if>>
/* 3. Apply — check for intimate nest suspicion reduction */
<<set _nestReduction to ($nestSuspReduction && $nestSuspReduction[_locName]) ? $nestSuspReduction[_locName] : 0>>
<<set _gain to Math.round(_gain * (1 - _nestReduction))>>
<<run window.addSuspicion(_gain)>>
/* 4. Output Warning */
<<if _nestReduction > 0>>
<div style="color:#44ff88; font-size:0.85em; margin-top:5px;">
☣ Nest dampened detection (−<<print Math.round(_nestReduction * 100)>>%)
</div>
<</if>>
<<if _witnessed>>
<div style="color:#ff4444; font-weight:bold; margin-top:5px;">
⚠ WITNESSED BY AUTHORITY! (+_gain Suspicion)
</div>
<<else>>
<div style="color:#ff8844; font-size:0.9em; margin-top:5px;">
Suspicion increased (+_gain)
</div>
<</if>>
<</nobr>><</widget>>/* =========================================================================
G1: FAMILY
Members: Elsa, Emily, Jewelz, Kylie, Lana, Winter
========================================================================= */
/* --- ELSA --- */
<<set $elsa = {
var: "elsa",
name: "Elsa",
group: "Family",
actress: "Elsa Jean",
description: "$name's $family, Elsa couldn't be more different from him. While $name is brooding and introspective, Elsa is lively and energetic — the kind of person who knows everyone and makes friends wherever she goes. She's always in the middle of a group, laughing at something, or organizing plans she'll probably forget to follow through on. She's fiercely loyal, even if she's not always reliable.",
/* Social Graph */
connections: ["jewelz", "emily", "chloe", "melody", "kylie", "lana", "scarlet", "amber", "melissa", "vina", "savannah", "kyler", "winter"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Amber's Class", weekend: "House" },
weekday: ["Amber's Class", "House", "$name's Dorm"],
weekend: ["$name's Dorm", "Clothing Store", "House"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- EMILY --- */
<<set $emily = {
var: "emily",
name: "Emily",
group: "Family",
actress: "Emily Willis",
description: "Emily is a quiet and reserved girl who has been through a lot in her young life. She was abused by her parents and has only recently found solace in the loving home of $name and his family. She is still healing from her past wounds and struggles to open up to others. Despite this, she is grateful for the kindness and support of her new family.",
/* Social Graph */
connections: ["jewelz", "elsa", "maya", "yulia", "kylie", "lana", "harmony", "laila", "adriana", "gabbie", "ash"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "homebody",
pairing: "high",
schedule: {
anchor: { weekday: "House", weekend: "House" },
weekday: ["House", "Adriana's Class", "School Hallway"],
weekend: ["House", "Department Store", "Park"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- JEWELZ --- */
<<set $jewelz = {
var: "jewelz",
name: "Jewelz",
group: "Family",
student: false, /* in a school group, but not a student */
actress: "Jewelz Blu",
description: "Jewelz is the oldest of the three siblings and has taken on a maternal role since their parents' passing. She works hard to provide for her family and is determined to give them a better life. Despite her tough exterior, she has a soft spot for those in need and is always willing to lend a helping hand.",
/* Social Graph */
connections: ["elsa", "emily", "kali", "kylie", "lana", "laila", "demi", "eva", "aria", "melissa", "katie", "jasmine", "kendra", "winter", "leda"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Restaurant", weekend: "House" },
weekday: ["House", "Restaurant", "$name's Dorm", "Department Store"],
weekend: ["House", "$name's Dorm", "Clothing Store", "Department Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KYLIE --- */
<<set $kylie = {
var: "kylie",
name: "Kylie",
group: "Family",
actress: "Kylie Quinn",
description: "Kylie is the youngest cousin of $name and has a playful and lively personality. She is always up for an adventure and loves to have fun, but can also be a bit of a handful at times — she says the thing everyone else was avoiding, then enjoys the reaction. She complains constantly about being treated like the baby of the family, largely by people responding to how she is behaving. She is more observant than she is given credit for, and notices when someone in the house is upset before they say anything, though she would not admit that is why she suddenly wants company.",
/* Social Graph */
connections: ["lana", "jewelz", "elsa", "emily", "harmony", "laila", "maya", "yulia", "adriana", "winter", "gabbie", "ash"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "restless",
pairing: "medium",
schedule: {
anchor: { weekday: "Adriana's Class", weekend: "Cousin's House" },
weekday: ["Adriana's Class", "Cousin's House", "School Hallway"],
weekend: ["Cousin's House", "$name's Dorm"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LANA --- */
<<set $lana = {
var: "lana",
name: "Lana",
group: "Family",
student: false, /* in a school group, but not a student */
actress: "Lana Rhoades",
description: "Lana is the confident and outspoken cousin of $name who isn't afraid to speak her mind. She's a bit of a tease and loves to poke fun at her cousins, but deep down she cares about them deeply. She is Kylie's older $family. She works at the Museum, to the surprise of many.",
/* Social Graph */
connections: ["kylie", "jewelz", "elsa", "emily", "blake", "kali", "winter", "natalie", "casey", "quinn", "uma"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "restless",
pairing: "medium",
schedule: {
anchor: { weekday: "Cousin's House", weekend: "Cousin's House" },
weekday: ["Cousin's House", "$name's Dorm"],
weekend: ["Cousin's House", "Clothing Store", "$name's Dorm", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- WINTER --- */
<<set $winter = {
var: "winter",
name: "Winter",
group: "Family",
student: false, /* in a school group, but not a student */
actress: "Winter Jade",
description: "Winter is the serious older $family who lost almost all contact when she went to law school and never looked back. She's sharp, efficient, and doesn't have time for small talk — but family is family, and she keeps an eye on her younger cousins from a distance. She is $name's oldest cousin.",
/* Social Graph */
connections: ["kylie", "jewelz", "elsa", "jessa", "lana", "quinn", "kendra"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "busy",
pairing: "low",
schedule: {
anchor: { weekday: "Courthouse", weekend: "Cousin's House" },
weekday: ["Cousin's House", "Real Estate"],
weekend: ["Cousin's House", "Department Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>/* =========================================================================
G2: CORE SUPPORT SYSTEM
Members: Aria, Claire, Demi, Eva, Isabella, Kailey, Karlee,
Laila, Marie, Melissa, Scarlet, Vina
========================================================================= */
/* --- ARIA --- */
<<set $aria = {
var: "aria",
name: "Aria",
group: "Core Support System",
actress: "Aria Lee",
description: "Aria is $name's girlfriend, a bright and cheerful college student who is always up for an adventure. She is confident and outgoing, and has a quick wit that can usually talk her way out of any situation — and, more often, talk other people into things. She likes having something arranged for the weekend and gets restless when nothing is. Her older sister Anya is protective to the point of interfering, which Aria finds exhausting and has never quite pushed back on. With $name she is affectionate and easy, though she assumes he will go along with whatever she has decided, and he generally does.",
/* Social Graph */
connections: ["anya", "eva", "ashly", "chanel", "vanna", "marie", "jewelz", "isabella", "alex", "violet"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "social",
pairing: "low",
schedule: {
anchor: { weekday: "Chanel's Class", weekend: "Aria's House" },
weekday: ["Chanel's Class", "Aria's House", "$name's Dorm"],
weekend: ["Aria's House", "House"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- CLAIRE --- */
<<set $claire = {
var: "claire",
name: "Claire",
group: "Core Support System",
actress: "Anna Claire Clouds",
description: "Claire lives to stir the pot. Confident and always pushing boundaries, she flirts like it's a game and enjoys bending rules—curfews, dress codes, and even emotional ones. Despite her provocative demeanor, she watches closely, testing reactions and subtly steering conversations. She likes to see how far people (and $name, her dormmate) will go.",
/* Social Graph */
connections: ["karlee", "scarlet", "myra", "molly", "jasmine", "uma", "aidra", "ariana", "harley", "carolina"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "restless",
pairing: "low",
schedule: {
anchor: { weekday: "$name's Dorm", weekend: "$name's Dorm" },
weekday: ["$name's Dorm", "School Pool", "School Rooftop"],
weekend: ["$name's Dorm", "School Pool", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- DEMI --- */
<<set $demi = {
var: "demi",
name: "Demi",
group: "Core Support System",
actress: "Demi Hawks",
description: "Demi is Laila's twin and a college student who sees the world through the lens of her camera. She is $name's neighbour and has helped his family after the deaths of their parents. She has an introverted nature, but becomes very talkative, even if a lot sarcastic, around those she cares about.",
/* Social Graph */
connections: ["laila", "caprice", "abella", "leah", "karlee", "mia", "jade", "adria", "rae", "kate"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "high",
schedule: {
anchor: { weekday: "Neighbor's House", weekend: "Neighbor's House" },
weekday: ["Mia's Class", "School Rooftop", "School Hallway"],
weekend: ["Neighbor's House", "Electronics Store", "Park"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- EVA --- */
<<set $eva = {
var: "eva",
name: "Eva",
group: "Core Support System",
actress: "Eva Lovia",
description: "Eva is a vibrant and charismatic college student who is always up for a challenge. She's a natural leader, with a quick wit and a sharp mind, and is not afraid to speak her truth. As $name's best friend, she's fiercely protective of him and values their friendship above all else.",
/* Social Graph */
connections: ["harmony", "alina", "aria", "chanel", "vanna", "yulia", "ashly", "isabella", "alex", "violet", "marie", "riley"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Chanel's Class", weekend: "Eva's House" },
weekday: ["Chanel's Class", "Eva's House", "$name's Dorm"],
weekend: ["Eva's House", "Gym", "$name's Dorm", "Spa"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ISABELLA --- */
<<set $isabella = {
var: "isabella",
name: "Isabella",
group: "Core Support System",
actress: "Isabella Nice",
description: "Isabella is a long-time friend of $name, and one of the school's lead cheerleaders. She channels her compassion and drive into performance and team leadership. She's become a respected figure in the gym, motivating younger cheerleaders and setting a standard for discipline and support.",
/* Social Graph */
connections: ["athena", "lacy", "chanel", "eva", "vanna", "aria", "ashly", "alex", "violet"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Cheerleader Track", weekend: "Cheerleader Track" },
weekday: ["Cheerleader Track", "Chanel's Class"],
weekend: ["Cheerleader Track", "Clothing Store", "Spa", "$name's Dorm"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KAILEY --- */
<<set $kailey = {
var: "kailey",
name: "Kailey",
group: "Core Support System",
actress: "Kylie Rocket",
description: "A close friend of $name’s, Kailey is cheerful, approachable, and always up for spending time together. She often hangs out at the square, chatting with $name about school, gossip, or life in general. Though not as wild as Uma, she loves the lively atmosphere and finds comfort in being part of the bustle. Loyal and curious, she’s the kind of friend who notices when $name seems “off” but doesn’t push too hard unless she’s worried.",
/* Social Graph */
connections: ["madi", "gina", "skylar", "avery", "lexi", "uma"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "School Hallway", weekend: "Town Square" },
weekday: ["Arcade", "School Hallway"],
weekend: ["Arcade", "Town Square", "$name's Dorm"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KARLEE --- */
<<set $karlee = {
var: "karlee",
name: "Karlee",
group: "Core Support System",
actress: "Karlee Grey",
description: "Karlee naturally takes charge of the dorm, setting routines and keeping things somewhat orderly—even if Claire and Scarlet tend to derail her plans. She's pragmatic, protective, and secretly likes the chaos around her (though she'd never admit it). She keeps one eye on her roommates, especially $name, unsure whether he needs support… or supervision.",
/* Social Graph */
connections: ["claire", "scarlet", "caprice", "abella", "leah", "demi", "mia", "jade", "adria", "rae"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "$name's Dorm", weekend: "$name's Dorm" },
weekday: ["$name's Dorm", "Library"],
weekend: ["$name's Dorm", "Park"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LAILA --- */
<<set $laila = {
var: "laila",
name: "Laila",
group: "Core Support System",
actress: "Lily Larimar",
description: "Laila is a kind-hearted and gentle soul who always puts others before herself. She is $name's neighbour and has helped his family after the deaths of their parents. With a quick smile and a listening ear, she has a way of making everyone feel welcome and at ease. She is Demi's twin.",
/* Social Graph */
connections: ["demi", "elsa", "kylie", "harmony", "maya", "emily", "adriana", "ash", "gabbie"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "high",
schedule: {
anchor: { weekday: "Neighbor's House", weekend: "Neighbor's House" },
weekday: ["Neighbor's House", "Adriana's Class", "School Hallway"],
weekend: ["Neighbor's House", "Department Store", "House"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MARIE --- */
<<set $marie = {
var: "marie",
name: "Marie",
group: "Core Support System",
actress: "XXlayna Marie",
description: "Marie is a warm and lively individual with a sparkling personality. She is in a loving relationship with Blake and values her friendships deeply — she is the one who keeps in touch, remembers the thing you mentioned once, and turns her dorm into somewhere people end up without planning to. She is openly affectionate and slightly embarrassing about Blake, which Myra never lets her forget. $name had a bit of a crush on her, but they have remained friends for years; she has always known, has never made anything of it, and has never brought it up.",
/* Social Graph */
connections: ["blake", "myra", "chanel", "vanna", "eva", "ashly", "isabella", "alex", "violet", "aria"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Marie's Dorm", weekend: "Marie's Dorm" },
weekday: ["Marie's Dorm", "Chanel's Class", "Cheerleader Track", "Sorority House"],
weekend: ["Marie's Dorm", "Clothing Store", "Cheerleader Track"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- SCARLET --- */
<<set $scarlet = {
var: "scarlet",
name: "Scarlet",
group: "Core Support System",
actress: "Scarlet Skies",
description: "Scarlet, one of $name's roommates, is sweet, bubbly, and curious to a fault. She never means harm — but her endless questions and unfiltered honesty often lead her into awkward or revealing moments, and she will repeat what she saw to the room without it occurring to her that she should not. Always eager to understand people better, she unintentionally uncovers more than she should. Her dormmates adore her, mostly. Karlee has given up explaining which things are meant to go unmentioned.",
/* Social Graph */
connections: ["claire", "karlee", "amber", "elsa", "athena", "chloe", "savannah", "kyler", "natalia"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "social",
pairing: "low",
schedule: {
anchor: { weekday: "Amber's Class", weekend: "$name's Dorm" },
weekday: ["Amber's Class", "$name's Dorm", "School Rooftop"],
weekend: ["$name's Dorm", "Cinema", "Beach"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- VINA --- */
<<set $vina = {
var: "vina",
name: "Vina",
group: "Core Support System",
actress: "Vina Sky",
description: "Vina is easygoing and bright, the kind of person who gets along with everyone without ever being the center of attention. She and $name don't run in the same circles anymore, but when they cross paths, it's never awkward — just familiar, like slipping back into an old routine.",
/* Social Graph */
connections: ["melissa", "jewelz", "elsa", "riley"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "Godmother's House", weekend: "Godmother's House" },
weekday: ["Veruca's Class", "Cafeteria"],
weekend: ["Gym", "Cafeteria"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MELISSA --- */
<<set $melissa = {
var: "melissa",
name: "Melissa",
group: "Core Support System",
student: false, /* in a school group, but not a student */
actress: "Melissa Moore",
description: "Melissa is warm, nurturing, and fiercely protective of the children she helped raise after their parents passed. She's the kind of woman who shows up with casseroles and advice whether you asked for it or not — and somehow, you're always glad she did. She is $name, Elsa and Jewelz's godmother.",
/* Social Graph */
connections: ["vina", "jewelz", "emily", "elsa", "luna"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Godmother's House", weekend: "Godmother's House" },
weekday: ["Library", "House"],
weekend: ["Spa", "Clothing Store", "House"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>/* =========================================================================
G3: CLOSE SCHOOL FRIENDS
Members: Maya, Alex, Melody, Ashly, Vanna, Violet, Caprice, Blake, Myra,
Haley, Riley, Gabbie, Adria, Jade, Savannah, Kyler, Nancy, Harmony
========================================================================= */
/* --- MAYA --- */
<<set $maya = {
var: "maya",
name: "Maya",
group: "Close School Friends",
actress: "Maya Woulfe",
description: "Maya is a bright and cheerful student who always has a smile on her face. She is a close friend of $name's and one of the first people he sees most mornings. Her laugh is loud and unmistakable and carries further than she realises, which she is teased about and has never tried to change. She is warm with almost everyone, remembers small things about people and brings them up later, and is usually the one who notices a person has been left out of a plan.",
/* Social Graph */
connections: ["emily", "yulia", "laila", "alex", "harmony", "adriana", "gabbie"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Adriana's Class", weekend: "Dormitory Hall" },
weekday: ["Adriana's Class", "School Hallway", "Dormitory Hall"],
weekend: ["Dormitory Hall"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ALEX --- */
<<set $alex = {
var: "alex",
name: "Alex",
group: "Close School Friends",
actress: "Alex Coal",
description: "Alex is a bright and cheerful person who lights up the room with her presence. She's confident and outgoing, but also has a kind and compassionate side, though her competitive side is very, very prevalent. As a student, she's always looking for new experiences and opportunities to learn and grow. She's quick-witted and loves to chat with friends over coffee or lunch.",
/* Social Graph */
connections: ["christie", "gina", "maya", "chanel", "vanna", "eva", "ashly", "isabella", "aria", "marie", "violet", "adria", "kyler"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "restless",
pairing: "low",
schedule: {
anchor: { weekday: "Chanel's Class", weekend: "Cafeteria" },
weekday: ["Chanel's Class", "School Rooftop", "Cafeteria"],
weekend: ["Cafeteria", "Spa", "Town Square"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MELODY --- */
<<set $melody = {
var: "melody",
name: "Melody",
group: "Close School Friends",
actress: "Melody Marks",
description: "Melody is a gentle and artistic individual who observes the world around her with curiosity and sensitivity. She is a good listener and values deep conversations, but may struggle to express herself in large groups or loud environments, where she goes quiet and lets the noise happen around her. One to one she is funnier and stranger than people expect. She has been Elsa's closest friend for more than ten years, and the two of them work as a pair — Elsa talking, Melody noticing. She is protective of that and would deny being so.",
/* Social Graph */
connections: ["elsa", "chloe", "amber", "emily", "athena", "lacy"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "homebody",
pairing: "high",
schedule: {
anchor: { weekday: "Amber's Class", weekend: "House" },
weekday: ["Amber's Class", "School Hallway", "House"],
weekend: ["Department Store", "School Hallway"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ASHLY --- */
<<set $ashly = {
var: "ashly",
name: "Ashly",
group: "Close School Friends",
actress: "Ashly Anderson",
description: "Ashly is Aria's shy and introverted friend, who often finds herself getting lost in the background. She's quiet and reserved, but has a hidden talent for observation and often notices things that others miss. Despite her shy nature, she has a deep loyalty to those she cares about and will do whatever it takes to protect them.",
/* Social Graph */
connections: ["aria", "vanna", "chanel", "anya", "eva", "marie", "isabella", "alex", "violet"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "high",
schedule: {
anchor: { weekday: "Chanel's Class", weekend: "Aria's House" },
weekday: ["Chanel's Class", "Aria's House", "School Hallway"],
weekend: ["Aria's House", "Dormitory Hall"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- VANNA --- */
<<set $vanna = {
var: "vanna",
name: "Vanna",
group: "Close School Friends",
actress: "Vanna Bardot",
description: "Vanna is a popular and charismatic college student who knows how to work the social scene. She's used to getting what she wants and can come across as spoiled or entitled at times. Despite her bratty exterior, she's deeply insecure and often uses her sharp tongue to hide her vulnerabilities.",
/* Social Graph */
connections: ["ashly", "chanel", "eva", "aria", "isabella", "alex", "violet", "marie", "haley", "rae"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "social",
pairing: "low",
schedule: {
anchor: { weekday: "Chanel's Class", weekend: "Sorority House" },
weekday: ["Chanel's Class", "School Rooftop", "Sorority House"],
weekend: ["Dormitory Hall", "Clothing Store", "Spa", "Cheerleader Track"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- VIOLET --- */
<<set $violet = {
var: "violet",
name: "Violet",
group: "Close School Friends",
actress: "Violet Starr",
description: "Violet is an affectionate person who has a tendency to be overly dramatic and demanding. She's used to getting her way and can come across as bratty or entitled to those who don't know her. Despite this, she's deeply loyal to those she cares about and will do anything to protect them. She has a special soft spot for $name, which can sometimes make her behave in ways that are less than flattering.",
/* Social Graph */
connections: ["caprice", "shazia", "vanna", "eva", "ashly", "isabella", "alex", "aria", "marie"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Chanel's Class", weekend: "Library" },
weekday: ["Chanel's Class", "School Hallway", "Library"],
weekend: ["Library", "Clothing Store", "Town Square"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- CAPRICE --- */
<<set $caprice = {
var: "caprice",
name: "Caprice",
group: "Close School Friends",
actress: "Little Caprice",
description: "Caprice is a unique and creative student who doesn't conform to traditional norms. She's a bit of a loner, but has a soft spot for those she cares about. Her dry sense of humor and sarcastic comments can sometimes be misinterpreted as aloofness. She often helps Shazia to run the library as part-time.",
/* Social Graph */
connections: ["violet", "shazia", "demi", "abella", "leah", "karlee", "jade", "adria"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Library", weekend: "Dormitory Hall" },
weekday: ["School Rooftop", "School Hallway", "Library"],
weekend: ["Library", "Department Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- BLAKE --- */
<<set $blake = {
var: "blake",
name: "Blake",
group: "Close School Friends",
actress: "Blake Blossom",
description: "Calm, affectionate, and grounded. Blake is Marie's girlfriend and brings a steady, comforting energy to the dorm. She enjoys quiet activities like reading or sketching and is known for her dry wit and soft-spoken nature. She's perfectly comfortable around $name despite his obvious crush on Marie and often engages in relaxed conversation.",
/* Social Graph */
connections: ["marie", "myra", "kali", "jewelz", "lana", "haley", "vina", "kenzie", "leda"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "high",
schedule: {
anchor: { weekday: "Marie's Dorm", weekend: "Marie's Dorm" },
weekday: ["Marie's Dorm", "Library", "Cheerleader Track"],
weekend: ["Marie's Dorm", "Clothing Store", "Cheerleader Track"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MYRA --- */
<<set $myra = {
var: "myra",
name: "Myra",
group: "Close School Friends",
actress: "Myra Moans",
description: "Myra is a sarcastic, chill music-lover who marches to her own beat — usually wearing earbuds. Myra has a sharp sense of humour and prefers observing to participating unless something piques her interest, at which point she is suddenly the most invested person in the room. She is Marie and Blake's roommate, and often jokes about their lovey-dovey attitudes, which is the closest she gets to saying she likes living with them. She has strong opinions about music and shares them whether or not anyone asked. She is harder to actually get to know than she appears.",
/* Social Graph */
connections: ["marie", "blake", "claire", "aidra", "jasmine", "carolina", "harley", "uma"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Marie's Dorm", weekend: "Marie's Dorm" },
weekday: ["Marie's Dorm", "School Rooftop", "School Hallway"],
weekend: ["Marie's Dorm", "Department Store", "Town Square"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- HALEY --- */
<<set $haley = {
var: "haley",
name: "Haley",
group: "Close School Friends",
actress: "Haley Reed",
description: "Haley is the public face of the mansion—bubbly and used to getting what she wants. She's the kind of rich that doesn't think about money because there's always more. Despite her privileged upbringing, she's genuinely friendly and curious about people outside her bubble. She met $name through Lana, who brought him to a mansion party, and she was instantly fascinated by someone so... normal.",
/* Social Graph */
connections: ["lana", "casey", "luna", "blake", "vina", "autumn", "kailey", "madi"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "social",
pairing: "low",
schedule: {
anchor: { weekday: "Mansion", weekend: "Mansion" },
weekday: ["Mansion", "Spa", "Cafeteria"],
weekend: ["Mansion", "Sorority House"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- RILEY --- */
<<set $riley = {
var: "riley",
name: "Riley",
group: "Close School Friends",
actress: "Riley Reid",
description: "Eva's best friend. Riley is the kind of person who blends into the background until she decides she likes you — then suddenly she's everywhere, talking your ear off about anything and everything. Eva says she's a lock that takes the right key, and once that lock opens, there's no closing it again.",
/* Social Graph */
connections: ["eva", "blake", "madi", "kenzie", "kailey", "vina", "veruca"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Veruca's Class", weekend: "Dormitory Hall" },
weekday: ["Veruca's Class", "Eva's House", "Dormitory Hall"],
weekend: ["Dormitory Hall", "Eva's House", "Library"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- GABBIE --- */
<<set $gabbie = {
var: "gabbie",
name: "Gabbie",
group: "Close School Friends",
actress: "Gabbie Carter",
description: "Gabbie is a lively and energetic person who brings a positive vibe to those around her. She's friendly, approachable, and always up for a new adventure. As a member of various clubs and organizations, she's passionate about meeting new people and trying new things, and is not afraid to be herself.",
/* Social Graph */
connections: ["adria", "yulia", "laila", "jade", "harmony", "adriana", "anya", "ash", "maya"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "Student Council", weekend: "Dormitory Hall" },
weekday: ["Adriana's Class", "School Hallway"],
weekend: ["Dormitory Hall", "Department Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ADRIA --- */
<<set $adria = {
var: "adria",
name: "Adria",
group: "Close School Friends",
actress: "Adria Rae",
description: "Adria is a driven and ambitious individual who takes her responsibilities seriously. She is a natural leader, confident in her abilities, and has a strong sense of justice. As the student council president, she is dedicated to making her school a better place for everyone — and she applies the rules evenly, including to people who expected an exception, which has cost her friendships she has decided she can accept losing. Gabbie handles the students Adria cannot. The job is smaller than the seriousness she brings to it, and she knows that.",
/* Social Graph */
connections: ["gabbie", "jade", "karlee", "rae", "leah", "mia", "anya", "caprice", "natalie"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Student Council", weekend: "Dormitory Hall" },
weekday: ["Mia's Class", "Library", "Dormitory Hall"],
weekend: ["Dormitory Hall", "Library"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- JADE --- */
<<set $jade = {
var: "jade",
name: "Jade",
group: "Close School Friends",
actress: "Jade Kush",
description: "Jade is a sharp and intelligent individual who isn't afraid to speak her mind. She's a skilled debater and researcher, always looking for ways to improve her arguments and persuade others. Her confidence can sometimes come across as intimidating, but she's ultimately driven by a desire to learn and grow.",
/* Social Graph */
connections: ["adria", "karlee", "gabbie", "shazia", "abella", "caprice", "mia", "natalie"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "busy",
pairing: "low",
schedule: {
anchor: { weekday: "Student Council", weekend: "Dormitory Hall" },
weekday: ["Mia's Class", "School Hallway", "Library"],
weekend: ["Dormitory Hall", "Library", "Department Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- SAVANNAH --- */
<<set $savannah = {
var: "savannah",
name: "Savannah",
group: "Close School Friends",
actress: "Savannah Sixx",
description: "Poised, polished, and perpetually prepared, Savannah is the intern who always has a backup plan and a well-organized binder. She's intelligent and thoughtful, considering every angle before speaking or acting. But beneath her confident exterior is a young woman carrying the weight of her parents' expectations — they mapped out her entire life, and she's never been asked what she wants. She's terrified of disappointing them, and she's begun to wonder if she's living her life or theirs. She admires Kyler's freedom, envies $name's quiet confidence, and hopes Megan might show her a different path.",
/* Social Graph */
connections: ["kyler", "keisha", "megan", "athena", "chloe", "elsa"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "medium",
schedule: {
anchor: { weekday: "Office", weekend: "Clothing Store" },
weekday: ["Amber's Class"],
weekend: ["Dormitory Hall", "Electronics Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KYLER --- */
<<set $kyler = {
var: "kyler",
name: "Kyler",
group: "Close School Friends",
actress: "Kyler Quinn",
description: "Bright, capable, and professional, Kyler shows up, meets deadlines, and handles feedback with grace. But underneath that competence is a quiet uncertainty — she has no idea what she actually wants to do with her life. She took this internship because it was available, because her parents said she needed experience, because everyone else seemed to have a plan and she didn't want to be left behind. She's friendly and approachable, not because she's performing, but because she genuinely likes people and finds connection easier than figuring out her own path.",
/* Social Graph */
connections: ["savannah", "keisha", "megan", "lacy", "amber", "chloe"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "high",
schedule: {
anchor: { weekday: "Office", weekend: "Dormitory Hall" },
weekday: ["Amber's Class"],
weekend: ["Dormitory Hall"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- NANCY --- */
<<set $nancy = {
var: "nancy",
name: "Nancy",
group: "Close School Friends",
actress: "Nancy Ace",
description: "Nancy runs the sorority with a blend of charm, manipulation, and genuine care. She's polished, poised, and always two steps ahead. She maintains the house's reputation, manages interpersonal drama, and ensures everything looks perfect for alumnae and university officials. Beneath the surface, she's exhausted and lonely—no one sees the president as a person, only a position.",
/* Social Graph */
connections: ["avi", "marie", "blake", "adriana", "lacy", "veruca", "riley", "adria", "natalie"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Sorority House", weekend: "Sorority House" },
weekday: ["Sorority House", "Library", "Student Council"],
weekend: ["Sorority House", "Cheerleader Track"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- HARMONY --- */
<<set $harmony = {
var: "harmony",
name: "Harmony",
group: "Close School Friends",
actress: "Harmony Wonder",
description: "Harmony is energetic and imaginative. She idolizes Eva and often tries to emulate her older sister's boldness, though her efforts are still rough around the edges. Naïve but sweet-natured, Harmony has a talent for making people smile — though she sometimes overhears more than she should and keeps surprising others with unexpected insights.",
/* Social Graph */
connections: ["eva", "alina", "kylie", "laila", "maya", "emily", "yulia", "adriana", "ash", "gabbie"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "high",
schedule: {
anchor: { weekday: "Adriana's Class", weekend: "Eva's House" },
weekday: ["Adriana's Class", "Eva's House", "School Rooftop"],
weekend: ["Eva's House", "Park", "Arcade"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>/* =========================================================================
G4: SCHOOL ACQUAINTANCES
Members: Athena, Lacy, Yulia, Leah, Abella, Avi, Nancy, Rae, Ash,
Ariana, Harley, Uma, Carolina, Natalie, Lulu, Molly, Kenzie,
Madi, Jasmine
========================================================================= */
/* --- ATHENA --- */
<<set $athena = {
var: "athena",
name: "Athena",
group: "School Acquaintances",
actress: "Athena Faris",
description: "Athena is a sweet and friendly girl who loves being a cheerleader. She is outgoing, energetic, and always looks on the bright side of things, sometimes past the point where anyone else can. She trains hard, turns up early, and is pleased for other people when they do well, without any of it being for show. Her innocence and kindness make her a beloved figure at school, and they also make her easy to steer — she takes what she is told at face value and rarely thinks to check. Lacy is her closest friend on the squad.",
/* Social Graph */
connections: ["isabella", "lacy", "elsa", "chloe", "scarlet", "amber", "avi", "savannah", "kyler"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Cheerleader Track", weekend: "Cheerleader Track" },
weekday: ["Amber's Class", "Cheerleader Track"],
weekend: ["Dormitory Hall", "Cheerleader Track", "Clothing Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LACY --- */
<<set $lacy = {
var: "lacy",
name: "Lacy",
group: "School Acquaintances",
actress: "Lacy Lennon",
description: "Lacy is a popular and confident cheerleader who knows how to get what she wants. She is sharp-tongued and calculating, always looking for ways to advance her social status, and keeps a running sense of where she stands with everyone on the squad. Despite her tough exterior, she has a soft spot for her friends and will do anything to protect them — she has taken the blame for other girls more than once, then been unpleasant about something minor soon after. Athena is the one she keeps closest.",
/* Social Graph */
connections: ["isabella", "athena", "amber", "melody", "chloe", "scarlet", "blake", "savannah", "kyler"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Cheerleader Track", weekend: "Cheerleader Track" },
weekday: ["Cheerleader Track", "Amber's Class"],
weekend: ["Spa", "Cheerleader Track", "Clothing Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- YULIA --- */
<<set $yulia = {
var: "yulia",
name: "Yulia",
group: "School Acquaintances",
actress: "Eva Elfie",
description: "Yulia is a soft-spoken foreign exchange student from Eastern Europe. She is still getting used to this way of life and can come across as a bit reserved or shy, though a good deal of that is simply the delay of working out how to say something before the conversation moves on. She is deeply curious and loves to learn new things, and asks questions other students do not think to ask because none of it is automatic to her. She is more direct in writing than in speech. She misses home and tends not to mention it.",
/* Social Graph */
connections: ["emily", "maya", "adriana", "harmony", "laila", "kylie", "eva"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "high",
schedule: {
anchor: { weekday: "Adriana's Class", weekend: "Dormitory Hall" },
weekday: ["Adriana's Class", "Dormitory Hall"],
weekend: ["Dormitory Hall", "Library"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LEAH --- */
<<set $leah = {
var: "leah",
name: "Leah",
group: "School Acquaintances",
actress: "Leah Gotti",
description: "Leah is a tall, athletic student and the star player of the school basketball team. She's outgoing, energetic, and always ready with a grin or a joke — the kind of person who makes friends instantly and forgets names just as fast. She's not the sharpest tool in the shed and she knows it, but she makes up for it with sheer enthusiasm and a willingness to try anything. Practice is her happy place, and she loves the simplicity of basketball: rules, goals, teamwork. She's loyal to her teammates, friendly to everyone, and genuinely believes life is better when you're laughing. Her scattermindedness means she's always losing things, forgetting appointments, or showing up to the wrong place — but her charm usually gets her out of trouble.",
/* Social Graph */
connections: ["alison", "abella", "alina", "caprice", "demi", "karlee"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Gym", weekend: "Gym" },
weekday: ["Gym", "Dormitory Hall"],
weekend: ["Gym", "Dormitory Hall"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ABELLA --- */
<<set $abella = {
var: "abella",
name: "Abella",
group: "School Acquaintances",
actress: "Abella Danger",
description: "Abella is a rebellious student who keeps to herself. She had a rough upbringing — a chaotic family, instability, and years of bullying before she made it to this new college. The bullying left scars, physical and emotional, and she's built a tough exterior to protect herself from being hurt again. She's quiet, sharp-tongued, and uses sarcasm as a shield. People either respect her space or leave her alone, and she prefers it that way. Fitness is her outlet — it's something she can control, something that makes her feel strong when she's felt powerless. She trains alone, late at night, when the gym is empty. She has a hidden creative side — sketches, graffiti art, poetry — that she shares with no one.",
/* Social Graph */
connections: ["leah", "alison", "alina", "caprice", "demi", "karlee"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "busy",
pairing: "low",
schedule: {
anchor: { weekday: "Gym", weekend: "Gym" },
weekday: ["Gym", "Cheerleader Track"],
weekend: ["Gym", "Cheerleader Track"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- AVI --- */
<<set $avi = {
var: "avi",
name: "Avi",
group: "School Acquaintances",
actress: "Avi Love",
description: "Avi is loud, opinionated, and unapologetically herself — qualities that make her both beloved and exhausting. She has been assigned a tutor for academic reasons and resents the implication that she needs help, which she does. She is brash to hide insecurity, confident to mask fear of failure, and would much rather be thought difficult than thought slow. She has filed $name under quiet, probably boring, and has not registered how often she ends up talking at him anyway.",
/* Social Graph */
connections: ["nancy", "myra", "gina"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Sorority House", weekend: "Sorority House" },
weekday: ["Sorority House", "Cafeteria", "$name's Dorm"],
weekend: ["Sorority House", "Cheerleader Track", "$name's Dorm"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- RAE --- */
<<set $rae = {
var: "rae",
name: "Rae",
group: "School Acquaintances",
actress: "Rae Lil Black",
description: "Rae spends time in detention for her consistently sharp tongue and rebellious classroom antics. She is clever and observant, often using her detention hours to size up others or plant ideas, and she reads a room well enough to know exactly what a comment will cost her before she makes it. She makes it anyway. Beneath her sarcasm, she hides a growing restlessness that detention only fuels — school has nothing to offer her that she wants, and the hours she is supposed to find punishing have become the part of the week she minds least.",
/* Social Graph */
connections: ["vanna", "ash", "mia", "kali", "leda", "karlee", "demi", "lexi", "avery"],
met: false,
meetingMethod: "contact",
/* Roaming Logic */
roamTrait: "restless",
pairing: "low",
schedule: {
anchor: { weekday: "Mia's Class", weekend: "Club" },
weekday: ["Detention Room", "Mia's Class"],
weekend: ["Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ASH --- */
<<set $ash = {
var: "ash",
name: "Ash",
group: "School Acquaintances",
actress: "Ash Hollywood",
description: "A quiet and reserved student, Ash is a creative and introspective person who loves to write and draw. She is struggling with anxiety and often feels overwhelmed by her emotions, but she is working hard to overcome her fears and build her confidence, in increments small enough that nobody else would notice them. She shows her work to almost no one. Crowds cost her something to be in, and she replays conversations afterwards looking for what she got wrong. Rae pulled her into detention once and she has been loosely associated with trouble ever since.",
/* Social Graph */
connections: ["rae", "mia", "harmony", "maya", "gabbie", "veruca"],
met: false,
meetingMethod: "contact",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "low",
schedule: {
anchor: { weekday: "Adriana's Class", weekend: "Dormitory Hall" },
weekday: ["Detention Room", "Adriana's Class"],
weekend: ["Sorority House"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ARIANA --- */
<<set $ariana = {
var: "ariana",
name: "Ariana",
group: "School Acquaintances",
actress: "Ariana Marie",
description: "A quieter presence at the pool, Ariana is a focused and dedicated swimmer. She’s not flashy but extremely disciplined, often arriving early and staying late to practice. While she keeps to herself most of the time, Ariana has a subtle intensity that can be intimidating to others. Beneath her stoic demeanor, however, she envies Harley's ability to be social and carefree. Ariana takes swimming seriously—it’s her escape and her anchor.",
/* Social Graph */
connections: ["aidra", "claire", "uma", "myra", "carolina", "harley", "molly", "jasmine"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "School Pool", weekend: "School Pool" },
weekday: ["School Pool", "Spa"],
weekend: ["School Pool", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- HARLEY --- */
<<set $harley = {
var: "harley",
name: "Harley",
group: "School Acquaintances",
actress: "Harley Dean",
description: "A bubbly, enthusiastic girl in her late teens, Harley thrives in group activities and is always chatting between laps. She’s competitive in a lighthearted way, often turning practice into friendly challenges. Harley enjoys being around people more than the swimming itself, and she’s known for dragging her friends into the pool even if they’re reluctant. She looks up to Ariana and often tries (sometimes too hard) to impress her.",
/* Social Graph */
connections: ["aidra", "claire", "uma", "myra", "carolina", "ariana", "molly", "jasmine"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "School Pool", weekend: "Department Store" },
weekday: ["School Pool", "Spa"],
weekend: ["Club", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- UMA --- */
<<set $uma = {
var: "uma",
name: "Uma",
group: "School Acquaintances",
actress: "Uma Jolie",
description: "A free-spirited young woman with a love for performing arts. On her free days, she brings life to the square with juggling, singing, or playing guitar for passersby. She thrives on the attention of strangers and the spontaneity of street life, though underneath her bright energy she sometimes feels adrift, unsure where her talent might take her. She views the Town Square as her stage, her escape, and her community all at once.",
/* Social Graph */
connections: ["aidra", "claire", "harley", "myra", "carolina", "ariana", "molly", "jasmine", "kailey"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "restless",
pairing: "low",
schedule: {
anchor: { weekday: "School Pool", weekend: "Town Square" },
weekday: ["School Pool", "Town Square", "Spa"],
weekend: ["Town Square", "Gym", "Clothing Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- CAROLINA --- */
<<set $carolina = {
var: "carolina",
name: "Carolina",
group: "School Acquaintances",
actress: "Carolina Sweets",
description: "Carolina is the free-spirited daughter of Mayor Nicole, growing up in the spotlight of politics and expectations. Though raised in a formal environment, she has always resisted the stiffness of her upbringing with her carefree attitude and strong ideals. Despite her rebellious streak, she shares a complex but loving relationship with her mother and is often seen helping around the Town Hall, where she quietly keeps tabs on things most adults miss.",
/* Social Graph */
connections: ["aidra", "claire", "harley", "myra", "uma", "ariana", "molly", "jasmine", "nicole", "lily"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "School Pool", weekend: "Town Hall" },
weekday: ["School Pool", "Town Hall", "Spa"],
weekend: ["Town Hall", "Arcade", "Clothing Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- NATALIE --- */
<<set $natalie = {
var: "natalie",
name: "Natalie",
group: "School Acquaintances",
actress: "Natalie Knight",
description: "Natalie is deep in her thesis and doesn't have time for small talk or social games. She is polite but distant, more interested in data and deadlines than who's dating whom — which makes her both a challenge and an opportunity for someone with secrets to hide. She has stripped her week down to the work and defends what is left of it. The library is effectively hers; she has a preferred desk and is unimpressed when it is taken. What happens after the thesis is submitted is a question she has been careful not to look at.",
/* Social Graph */
connections: ["anya", "nancy", "karlee", "anya", "amber", "chanel"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "busy",
pairing: "normal",
schedule: {
anchor: { weekday: "Library", weekend: "Sorority House" },
weekday: ["Staff Room"],
weekend: ["Library"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LULU --- */
<<set $lulu = {
var: "lulu",
name: "Lulu",
group: "School Acquaintances",
actress: "Lulu Chu",
description: "A bubbly and eccentric regular who practically lives at the cinema. Lulu knows every film showing, quotes lines in conversation, and has a larger-than-life personality. Though some find her exhausting, her enthusiasm is infectious. She thrives on sharing her opinions (whether asked or not), and she dreams of one day writing or directing films herself.",
/* Social Graph */
connections: ["kenzie", "may", "molly", "lana", "leda", "kali", "blake"],
met: false,
meetingMethod: "contact",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "School Hallway", weekend: "Cinema" },
weekday: ["School Pool", "Cinema", "Department Store"],
weekend: ["Cinema", "Arcade", "School Pool"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MOLLY --- */
<<set $molly = {
var: "molly",
name: "Molly",
group: "School Acquaintances",
actress: "Molly Little",
description: "Molly is Lulu’s close friend and frequent movie buddy, often dragged along to screenings she’d never have chosen herself. More down-to-earth and pragmatic than Lulu, she balances her friend’s wild energy with level-headed humor. Molly enjoys films too, but for her, it’s more about the company than the cinema. She’s supportive but not afraid to poke fun at Lulu’s dramatic antics, making their friendship a mix of banter and genuine loyalty.",
/* Social Graph */
connections: ["aidra", "may", "lulu", "claire", "myra", "kali", "harley", "carolina", "jasmine"],
met: false,
meetingMethod: "contact",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "School Pool", weekend: "Cinema" },
weekday: ["School Pool", "Cinema", "Arcade"],
weekend: ["Cinema", "Arcade", "School Pool"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KENZIE --- */
<<set $kenzie = {
var: "kenzie",
name: "Kenzie",
group: "School Acquaintances",
actress: "Kenzie Reeves",
description: "Kenzie is a sharp, quick-witted high school student who treats the arcade like her second home. She is especially competitive in fighting games and rhythm challenges, often dominating the leaderboards, and is well aware that being the best player in a room this size is not the achievement other people treat it as. She hides her softer, goofier side behind a wall of snark and skill. Madi sees more of it than anyone. She spends more evenings there than at home and does not particularly want to be asked about that.",
/* Social Graph */
connections: ["lulu", "may", "madi", "natalia", "myra", "kali", "leda", "kylie"],
met: false,
meetingMethod: "contact",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "Arcade", weekend: "Club" },
weekday: ["Clothing Store", "Cinema", "Arcade"],
weekend: ["Cinema", "Arcade", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MADI --- */
<<set $madi = {
var: "madi",
name: "Madi",
group: "School Acquaintances",
actress: "Madi Collins",
description: "Madi is the relaxed, cheerful counterbalance to Kenzie. She doesn’t take gaming too seriously but has a knack for unexpectedly winning through pure luck or weird strategies. She’s social, flirty, and loves the energy of the arcade more than the games themselves. She knows everyone and is often the one convincing Natalia to let them hang out after hours.",
/* Social Graph */
connections: ["gina", "lexi", "kenzie", "natalia", "avery", "skylar", "kailey"],
met: false,
meetingMethod: "contact",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "Arcade", weekend: "Club" },
weekday: ["Electronics Store", "Arcade"],
weekend: ["Cinema", "Arcade", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- JASMINE --- */
<<set $jasmine = {
var: "jasmine",
name: "Jasmine",
group: "School Acquaintances",
actress: "Jasmine Grey",
description: "A bubbly college girl who works part-time at the restaurant to cover her expenses. Jasmine is friendly and chatty, always quick with a smile or a laugh, but she tends to get distracted talking to customers rather than focusing on her orders. She’s studying communications, which shows in her natural way of connecting with people. Though clumsy at times, her warmth makes her memorable to the regulars.",
/* Social Graph */
connections: ["katie", "jewelz", "kendra", "aidra", "claire", "uma", "myra", "carolina", "harley", "molly", "ariana"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "social",
pairing: "high",
schedule: {
anchor: { weekday: "School Pool", weekend: "Restaurant" },
weekday: ["Restaurant", "Arcade", "Library"],
weekend: ["Restaurant", "Arcade", "School Pool"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- CHLOE --- */
<<set $chloe = {
var: "chloe",
name: "Chloe",
group: "School Acquaintances",
actress: "Chloe Temple",
description: "Chloe is one of Elsa's classmates and one of the most approachable students at school. She's upbeat, supportive, and has a talent for putting others at ease. Whether it's group projects or hallway chats, Chloe is the kind of person who makes you feel like you matter. She tends to follow the rules but isn't afraid to question them—especially when something feels off.",
/* Social Graph */
connections: ["elsa", "melody", "amber", "lacy", "athena", "scarlet", "laila", "kailey"],
met: false,
meetingMethod: "contact",
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Amber's Class", weekend: "Dormitory Hall" },
weekday: ["Amber's Class", "School Hallway", "Dormitory Hall"],
weekend: ["Dormitory Hall", "Clothing Store", "Park"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>/* =========================================================================
G5: SCHOOL AUTHORITY FIGURES
Members: Chanel, Adriana, Amber, Christie, Gina, Shazia, Anya, Aidra, Veruca, Mia
========================================================================= */
/* --- CHANEL --- */
<<set $chanel = {
var: "chanel",
name: "Chanel",
group: "School Authority Figures",
actress: "Chanel Preston",
description: "Professor Chanel is a highly respected and accomplished academic who is known for her tough but fair approach to teaching. She's a brilliant professor with a deep understanding of human behavior and is always willing to lend a helping hand to her students. With her sharp mind and quick wit, she's a force to be reckoned with in the classroom.",
/* Social Graph */
connections: ["eva", "ashly", "vanna", "adriana", "amber", "aria", "marie", "isabella", "alex", "violet", "natalie", "veruca", "mia", "aidra"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Chanel's Class", weekend: "Library" },
weekday: ["Chanel's Class", "Library", "Staff Room"],
weekend: ["Library", "Town Square"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ADRIANA --- */
<<set $adriana = {
var: "adriana",
name: "Adriana",
group: "School Authority Figures",
actress: "Adriana Chechik",
description: "Professor Adriana is a kind-hearted and highly respected professor who teaches with enthusiasm and dedication. She is passionate about helping her students and has taken Emily under her wing, and is always willing to lend a listening ear or offer guidance when needed. Her lectures tend to overrun because a question took her somewhere more interesting than her notes. Students who stay silent in other classes speak in hers. She assumes people are arguing in good faith, which is usually right and occasionally lets a student waste half an hour of everyone's time.",
/* Social Graph */
connections: ["emily", "chanel", "amber", "kylie", "harmony", "yulia", "maya", "laila", "veruca", "mia", "aidra", "ash", "gabbie"],
met: true,
meetingMethod: null,
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Adriana's Class", weekend: "Gym" },
weekday: ["Adriana's Class", "Library", "Staff Room"],
weekend: ["Gym", "Spa", "Cinema"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- AMBER --- */
<<set $amber = {
var: "amber",
name: "Amber",
group: "School Authority Figures",
actress: "Britney Amber",
description: "Amber is a compassionate and understanding professor who genuinely cares about her students. She notices when someone has gone quiet over a few weeks and asks about it rather than letting it pass. Her sense of humour is easy and a little self-deprecating, and she uses it to take the pressure out of a room — a class of hers is rarely tense. The welcoming atmosphere is deliberate: she believes students learn badly when they are afraid of being wrong, so she makes being wrong cheap. It also means her classes run slowly, and she is not always firm when firmness is what a student actually needs.",
/* Social Graph */
connections: ["elsa", "chloe", "melody", "adriana", "lacy", "scarlet", "athena", "veruca", "mia", "aidra", "kyler", "savannah"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Amber's Class", weekend: "Cafeteria" },
weekday: ["Amber's Class", "Cafeteria", "Staff Room"],
weekend: ["Cafeteria", "Department Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- CHRISTIE --- */
<<set $christie = {
var: "christie",
name: "Christie",
group: "School Authority Figures",
actress: "Christie Stevens",
description: "Christie is a caring and dedicated person who pours her heart into everything she does. As the owner of the cafeteria, she is always looking for ways to improve and make her customers happy. She is passionate about cooking and loves to experiment with new recipes and flavours, not all of which work — she changes the menu more often than anyone has asked her to. She is in before the building opens and still there when it is locked. She takes complaints personally, which her staff have learned to shield her from.",
/* Social Graph */
connections: ["gina", "alex", "veruca", "mia"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Cafeteria", weekend: "Cafeteria" },
weekday: ["Cafeteria"],
weekend: ["Restaurant", "Cafeteria", "Cinema"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- GINA --- */
<<set $gina = {
var: "gina",
name: "Gina",
group: "School Authority Figures",
actress: "Gina Valentina",
description: "Gina is a kind and welcoming person who always has a smile on her face. She is a great listener and has a way of making everyone feel at ease. As the barmaid at the cafeteria, she is always ready to lend a helping hand or offer a sympathetic ear — people tell her things they have not told their friends, mostly because she asks for none of it and repeats none of it either. Christie runs the kitchen; Gina runs the room. She has a temper that surfaces rarely and only on someone else's behalf.",
/* Social Graph */
connections: ["christie", "alex", "kali", "myra"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "high",
schedule: {
anchor: { weekday: "Cafeteria", weekend: "Cafeteria" },
weekday: ["Cafeteria", "Arcade"],
weekend: ["Cafeteria", "Arcade", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- SHAZIA --- */
<<set $shazia = {
var: "shazia",
name: "Shazia",
group: "School Authority Figures",
actress: "Shazia Sahari",
description: "Shazia is the soft-spoken, gentle librarian at the school. Always tucked behind a desk or hidden between tall shelves, she speaks in hushed tones and avoids confrontation. Though shy, her eyes light up when talking about books or helping a student find the perfect read. Shazia often fades into the background—making her unnoticed, but never unkind.",
/* Social Graph */
connections: ["violet", "caprice", "jade", "adria", "anya", "ash"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "low",
schedule: {
anchor: { weekday: "Library", weekend: "Library" },
weekday: ["Library"],
weekend: ["Library"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ANYA --- */
<<set $anya = {
var: "anya",
name: "Anya",
group: "School Authority Figures",
actress: "Anya Olsen",
description: "Anya is Aria's older sister — strong-willed, protective, and occasionally overbearing. She's assertive and sharp-tongued, always looking out for Aria's well-being. Though she doesn't always approve of Aria's choices (especially involving $name), she's fiercely loyal and willing to step in when things get complicated. She works as an assistant Professor.",
/* Social Graph */
connections: ["aria", "marie", "alina", "natalie", "veruca"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "busy",
pairing: "low",
schedule: {
anchor: { weekday: "Staff Room", weekend: "Aria's House" },
weekday: ["Aria's House", "Library", "Staff Room"],
weekend: ["Aria's House", "Library"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- AIDRA --- */
<<set $aidra = {
var: "aidra",
name: "Aidra",
group: "School Authority Figures",
actress: "Aidra Fox",
description: "A woman in her mid-30s with a sharp, athletic build, Aidra is the school’s swimming and physical education instructor. Confident, disciplined, and straightforward, she runs the pool like a drill sergeant but has a dry sense of humor that peeks through when least expected. Aidra values perseverance and hates laziness, though she secretly softens when she sees a student truly struggling. She’s respected (and a little feared) by most who train under her.",
/* Social Graph */
connections: ["molly", "uma", "alison", "adriana", "chanel", "harley", "ariana", "carolina", "mia", "jasmine", "claire", "molly", "myra"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "restless",
pairing: "medium",
schedule: {
anchor: { weekday: "School Pool", weekend: "School Pool" },
weekday: ["School Pool", "Staff Room"],
weekend: ["School Pool", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- VERUCA --- */
<<set $veruca = {
var: "veruca",
name: "Veruca",
group: "School Authority Figures",
actress: "Veruca James",
description: "Veruca is a support teacher. She is the kind of teacher who students remember long after they graduate — not because she's loud or memorable, but because she actually saw them. She works quietly in the background, helping kids who fall through the cracks, and she's far more observant than most people give her credit for. She's shy around adults, but comes alive when she's helping a student who needs her.",
/* Social Graph */
connections: ["vina", "blake", "riley", "adriana", "chanel", "mia", "haley", "kenzie", "kailey", "madi", "luna", "shazia"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "low",
schedule: {
anchor: { weekday: "Veruca's Class", weekend: "Library" },
weekday: ["Detention Room", "Cafeteria", "Staff Room"],
weekend: ["Cafeteria", "Clothing Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MIA --- */
<<set $mia = {
var: "mia",
name: "Mia",
group: "School Authority Figures",
actress: "Mia Malkova",
description: "The school psychologist, Mia is a warm and caring person who is dedicated to helping her students work through their problems. She has a gentle smile and a calming presence that puts everyone at ease, and she is patient in a way most of the staff are not — students circle a subject for a long time before reaching it, and she lets them. She hears a great deal about what happens in the building and repeats none of it. Her own life comes up rarely; she is more comfortable being the person asking, and has arranged things so that she usually is.",
/* Social Graph */
connections: ["rae", "karlee", "ash", "adriana", "chanel", "shazia", "jade", "adria", "abella", "caprice", "demi", "leah", "natalie"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "high",
schedule: {
anchor: { weekday: "Mia's Class", weekend: "Cafeteria" },
weekday: ["Mia's Class", "Cafeteria", "Detention Room", "Staff Room"],
weekend: ["Cafeteria", "Clothing Store", "Spa"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>/* =========================================================================
G6: TOWN FOLKS
Members: Kali, Skylar, Kate, Alina, Luna, Casey, Nikki, Quinn, Kenna,
Caitlyn, Autumn, Stella, Momo, Megan, May, Katie, Kendra,
Natalia, Avery, Lexi, Leda, Alison
========================================================================= */
/* --- KALI --- */
<<set $kali = {
var: "kali",
name: "Kali",
group: "Town Folks",
actress: "Kali Roses",
description: "Kali is a free-spirited girl with a quirky sense of style and a love for alternative music. Working at the cozy coffee shop helps her earn extra cash while staying close to her best friend Jewelz, who often swings by after classes. Kali's warm energy draws people in, but she's got a streak of independence that means she doesn't like to be tied down.",
/* Social Graph */
connections: ["jewelz", "skylar", "kate", "quinn", "kendra", "natalia", "may", "leda"],
met: true,
meetingMethod: "null",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Department Store", weekend: "Department Store" },
weekday: ["Department Store", "House", "Electronics Store"],
weekend: ["Department Store", "House", "Cinema", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- SKYLAR --- */
<<set $skylar = {
var: "skylar",
name: "Skylar",
group: "Town Folks",
actress: "Skylar Vox",
description: "Skylar is organized, ambitious, and has an eye for fashion trends. As assistant manager, she juggles schedules, sales goals, and customer complaints with a calm, professional demeanor. Though she enjoys the style and buzz of the boutique, she's always thinking ahead—saving for college and dreaming of someday running her own fashion line.",
/* Social Graph */
connections: ["kali", "kate", "momo", "autumn", "quinn", "kendra"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Clothing Store", weekend: "Clothing Store" },
weekday: ["Clothing Store"],
weekend: ["Clothing Store", "Town Square"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KATE --- */
<<set $kate = {
var: "kate",
name: "Kate",
group: "Town Folks",
actress: "Kate Kuray",
description: "Kate carries her camera everywhere, capturing candid moments and mall events for local magazines and social media pages. She has a creative, observant nature and loves to find beauty in the everyday bustle of shoppers and vendors. Her style is casual and practical, and she's always ready to chase a sunset or capture a smile.",
/* Social Graph */
connections: ["skylar", "kali", "quinn", "kendra", "momo", "autumn"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "restless",
pairing: "low",
schedule: {
anchor: { weekday: "Electronics Store", weekend: "Electronics Store" },
weekday: ["Town Square", "Electronics Store"],
weekend: ["Town Square", "Electronics Store"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ALINA --- */
<<set $alina = {
var: "alina",
name: "Alina",
group: "Town Folks",
actress: "Alina Lopez",
description: "Alina runs the small-group sessions at the gym and knows everyone's programme by heart, which leaves her plenty of spare attention for everyone's business. Eva and Harmony's older sister and fiercely on their side — though she'll happily argue $name's case to anyone who'll listen, usually while joking that he picked the wrong girlfriend and should have gone for Eva. It's a joke she's made for years and nobody has ever asked her to stop.",
/* Social Graph */
connections: ["leah", "alison", "abella", "eva", "harmony", "katie", "anya", "natalia"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Gym", weekend: "Eva's House" },
weekday: ["Gym", "Eva's House"],
weekend: ["Eva's House", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LUNA --- */
<<set $luna = {
var: "luna",
name: "Luna",
group: "Town Folks",
actress: "Lexi Luna",
description: "Luna is the rich widow, owner of the biggest mansion in town and the wealthiest woman. She is observant, quiet, and keeps to herself, often lost in books or wandering the extensive mansion grounds alone. There is a loneliness to her that she masks with politeness — she is unfailingly courteous, remembers what people tell her, and gives away nothing in return. Most of the house goes unused. Casey and Haley are the closest thing she has to regular company, and she has never worked out how to ask anyone to stay longer.",
/* Social Graph */
connections: ["haley", "casey"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "low",
schedule: {
anchor: { weekday: "Mansion", weekend: "Mansion" },
weekday: ["Mansion", "Library"],
weekend: ["Mansion", "Spa", "Real Estate"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- CASEY --- */
<<set $casey = {
var: "casey",
name: "Casey",
group: "Town Folks",
actress: "Casey Calvert",
description: "Casey is the heir to the family fortune and carries that weight like armor. Standoffish, sharp-tongued, and perpetually unimpressed, she doesn't bother with pleasantries or people she deems unworthy. Despite her icy exterior, she formed an unlikely friendship with Lana—something about Lana's warmth and authenticity cracked through Casey's defenses. Through Lana, she was reluctantly introduced to $name.",
/* Social Graph */
connections: ["lana", "kylie", "haley", "luna"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "busy",
pairing: "medium",
schedule: {
anchor: { weekday: "Mansion", weekend: "Mansion" },
weekday: ["Mansion", "Library", "Cousin's House"],
weekend: ["Mansion", "Cousin's House"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- NIKKI --- */
<<set $nikki = {
var: "nikki",
name: "Nikki",
group: "Town Folks",
actress: "Nicole Doshi",
description: "Nikki has been running the spa for years and knows how to read people by the tension in their shoulders. She's the kind of person who listens more than she talks, but when she does speak, it's usually something worth hearing. Her hands are steady, her voice is soft, and she has a way of making people feel safe — which makes her both useful and dangerous to someone with secrets.",
/* Social Graph */
connections: ["kali", "skylar", "kate", "quinn", "kenna", "autumn", "momo", "lacy", "keisha"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "busy",
pairing: "medium",
schedule: {
anchor: { weekday: "Spa", weekend: "Spa" },
weekday: ["Spa"],
weekend: ["Spa"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- QUINN --- */
<<set $quinn = {
var: "quinn",
name: "Quinn",
group: "Town Folks",
actress: "Quinn Wilde",
description: "Quinn is in her mid-20s and already one of the top agents in town. She's polished, confident, and has a smile that makes people trust her instantly — which is exactly how she closes deals. She knows the value of every property in town, and she's always looking for her next opportunity. Whether that opportunity is a house or a person is hard to tell.",
/* Social Graph */
connections: ["kenna", "skylar", "kate", "kali", "kendra", "nikki", "winter"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Real Estate", weekend: "Real Estate" },
weekday: ["Real Estate", "Gym"],
weekend: ["Spa", "Gym", "Real Estate"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KENNA --- */
<<set $kenna = {
var: "kenna",
name: "Kenna",
group: "Town Folks",
actress: "Kendra Lust",
description: "Kenna has been running the real estate office for over a decade and knows more about the town's secrets than anyone else in the building. She's the one who keeps the office running, handles the paperwork, and quietly watches everything that happens. She's warm and approachable, but she doesn't miss a thing — and she remembers everything.",
/* Social Graph */
connections: ["quinn", "skylar", "kate", "kali", "nikki", "winter"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Real Estate", weekend: "Real Estate" },
weekday: ["Real Estate", "Library"],
weekend: ["Cinema", "Library", "Real Estate"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- CAITLYN --- */
<<set $caitlyn = {
var: "caitlyn",
name: "Caitlyn",
group: "Town Folks",
actress: "Chloe Cherry",
description: "Caitlyn had dreams of studying design in a big city, but family obligations forced her to stay behind and help run the hotel. She is good at the work and quietly resents being good at it. Guests get a practiced smile and thinly veiled eye-rolls, the second one usually a moment too early. She has not given the design up entirely — small things about the hotel have been improved since she started, none of them asked for and none of them mentioned. She talks about leaving in a way that has slowly become a habit rather than a plan.",
/* Social Graph */
connections: ["autumn", "momo", "stella", "anya", "casey", "alina", "katie"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "low",
schedule: {
anchor: { weekday: "Hotel", weekend: "Hotel" },
weekday: ["Cinema", "Library"],
weekend: ["Cinema", "Library", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- AUTUMN --- */
<<set $autumn = {
var: "autumn",
name: "Autumn",
group: "Town Folks",
actress: "Autumn Falls",
description: "Autumn is a rising pop star and social media icon who frequently chooses this hotel as her retreat from the spotlight. She loves the luxurious comfort and the anonymity the town provides, where enough people do not recognise her that she can be left alone. Charming and effortlessly magnetic, she is often seen lounging poolside or ordering elaborate room service. The charm is genuine and also well practised, and it is not always easy to tell which is running. She is quieter when there is no one to be charming at.",
/* Social Graph */
connections: ["caitlyn", "momo", "stella", "kate", "skylar", "nikki", "lily", "vanna"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "restless",
pairing: "medium",
schedule: {
anchor: { weekday: "Hotel", weekend: "Hotel" },
weekday: ["Cinema", "Club", "Spa"],
weekend: ["Cinema", "Spa", "Club", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- STELLA --- */
<<set $stella = {
var: "stella",
name: "Stella",
group: "Town Folks",
actress: "Stella Cox",
description: "A woman in her early thirties with tired but kind eyes, Stella has worked at the hotel for years as part of the cleaning staff. She’s practical, no-nonsense, and knows the building better than anyone. Despite her gruff tone at times, she cares about people and often notices more than she lets on. She keeps her head down most of the time but has a sharp intuition about the guests and staff around her.",
/* Social Graph */
connections: ["caitlyn", "momo", "autumn", "jasmine", "kendra"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Hotel", weekend: "Hotel" },
weekday: ["Clothing Store", "Restaurant", "Spa"],
weekend: ["Department Store", "Restaurant"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MOMO --- */
<<set $momo = {
var: "momo",
name: "Momo",
group: "Town Folks",
actress: "Momo Sakura",
description: "Momo is a Japanese model who stays at the hotel during her frequent work trips. She's elegant, composed, and always perfectly dressed — but there's a loneliness behind her polished exterior. She's used to people wanting things from her, which makes her cautious, but also deeply perceptive. She speaks in short, deliberate sentences, as if she's choosing every word carefully.",
/* Social Graph */
connections: ["caitlyn", "stella", "autumn", "kate", "skylar", "kendra", "nikki", "rae", "lulu"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Hotel", weekend: "Hotel" },
weekday: ["Cinema", "Restaurant", "Library"],
weekend: ["Clothing Store", "Cinema", "Spa"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MEGAN --- */
<<set $megan = {
var: "megan",
name: "Megan",
group: "Town Folks",
actress: "Megan Rain",
description: "Megan is the kind of supervisor who makes you forget she's your boss. In her early 30s, she's warm, approachable, and genuinely invested in the success of her team — she remembers birthdays, checks in on personal projects, and always has time for a quick chat. But beneath that easygoing exterior is a sharp, experienced leader who built this company from the ground up. She's fair and understanding, but she's not a pushover — she expects competence, integrity, and effort. She has a dry sense of humor that catches people off guard, and she's not afraid to laugh at herself. Megan is the glue of the office, the person everyone goes to for advice, and she carries the weight of that role with surprising grace. She's protective of her interns — she sees them as people first, workers second.",
/* Social Graph */
connections: ["nicole", "chanel", "kyler", "savannah", "kendra", "keisha"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Office", weekend: "Office" },
weekday: ["Restaurant", "Library"],
weekend: ["Restaurant", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- MAY --- */
<<set $may = {
var: "may",
name: "May",
group: "Town Folks",
actress: "Maya Bijou",
description: "A girl working behind the counter at the cinema. May is often bored and rolls her eyes at endless customer requests, but beneath her sarcasm she’s genuinely observant. She likes chatting with familiar faces and quietly pays attention to the people who come and go, making her a surprising source of gossip and information.",
/* Social Graph */
connections: ["lulu", "molly", "leda", "jewelz", "kali", "natalia", "katie", "caitlyn"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Cinema", weekend: "Cinema" },
weekday: ["Cinema", "Library"],
weekend: ["Cinema", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KATIE --- */
<<set $katie = {
var: "katie",
name: "Katie",
group: "Town Folks",
actress: "Katie Kush",
description: "A college student in her early twenties studying business. Katie works alongside Jasmine to help pay for tuition. Unlike Jasmine, she's more composed and practical, often stepping in to smooth over mistakes or keep things on track. She's ambitious and takes her job seriously, seeing it as a chance to learn management skills from Kendra. While she comes across as calm and responsible, her dry sense of humor sneaks out when she and Jasmine are alone.",
/* Social Graph */
connections: ["jasmine", "kendra", "alina", "jewelz", "may", "natalia", "caitlyn"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "medium",
schedule: {
anchor: { weekday: "Restaurant", weekend: "Restaurant" },
weekday: ["Cinema", "Library", "Restaurant"],
weekend: ["Library", "Restaurant"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KENDRA --- */
<<set $kendra = {
var: "kendra",
name: "Kendra",
group: "Town Folks",
actress: "Kendra Spades",
description: "In her late thirties, Kendra runs the restaurant with a mix of discipline and care. She started the business with little more than determination and has kept it thriving through sheer willpower. She’s organized, watchful, and doesn’t let mistakes slide easily, but her staff respects her because she protects them fiercely. To Kendra, the restaurant isn’t just a business—it’s her legacy.",
/* Social Graph */
connections: ["jasmine", "katie", "megan", "jewelz", "keisha", "nikki"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "busy",
pairing: "low",
schedule: {
anchor: { weekday: "Restaurant", weekend: "Restaurant" },
weekday: ["Restaurant"],
weekend: ["Town Square", "Restaurant"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- NATALIA --- */
<<set $natalia = {
var: "natalia",
name: "Natalia",
group: "Town Folks",
actress: "Sweetie Fox",
description: "Natalia runs the arcade with flair and personality. A well-known cosplayer in the local scene, she is often dressed in elaborate costumes inspired by anime, video games, or fantasy media — whether there's an event or not. She is passionate about games and creating a space where people feel safe to be themselves, and she is firmer about that than her manner suggests; anyone making the room unpleasant is asked to leave. She knows every cabinet's fault by sound. The place runs on her enthusiasm more than on money.",
/* Social Graph */
connections: ["kenzie", "madi", "skylar", "shazia", "kate", "nikki", "alina", "anya", "may", "katie"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "weekendSocial",
pairing: "low",
schedule: {
anchor: { weekday: "Arcade", weekend: "Arcade" },
weekday: ["Arcade"],
weekend: ["Arcade", "Library"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- AVERY --- */
<<set $avery = {
var: "avery",
name: "Avery",
group: "Town Folks",
actress: "Avery Black",
description: "A confident and magnetic presence, Avery is one of the club’s most recognizable regulars, often drawing attention on the dance floor. She’s outgoing, flirtatious, and enjoys being at the center of the action. Beneath her glamour, however, Avery craves connection; she’s looking for more than just fleeting fun, though she hides that vulnerability under her dazzling energy.",
/* Social Graph */
connections: ["leda", "lexi", "kali", "lana", "gina", "kailey", "madi"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Club", weekend: "Club" },
weekday: ["Arcade", "Club"],
weekend: ["Arcade", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LEXI --- */
<<set $lexi = {
var: "lexi",
name: "Lexi",
group: "Town Folks",
actress: "Lexi Lore",
description: "In her mid-twenties, Lexi is sharp, witty, and quick on her feet. She’s been working behind the bar long enough to know everyone’s secrets—or at least what they’ll spill after a few drinks. Confident and playful, she knows how to keep conversations flowing while keeping an eye on the crowd. Despite her lighthearted exterior, she’s protective of her space and won’t hesitate to shut down trouble when she sees it.",
/* Social Graph */
connections: ["casey", "kali", "leda", "avery", "kailey", "gina", "kenzie", "madi", "may"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Club", weekend: "Club" },
weekday: ["Arcade", "Club"],
weekend: ["Arcade", "Club"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LEDA --- */
<<set $leda = {
var: "leda",
name: "Leda",
group: "Town Folks",
actress: "Leda Elizabeth",
description: "The life of the club, Leda commands the music booth with an infectious energy. With headphones always around her neck and a smile that never fades, she thrives on keeping the dance floor alive. In her early twenties, she’s bold, creative, and lives in the moment. Leda has a rebellious streak—she doesn’t care much about rules, only about vibes, rhythm, and freedom.",
/* Social Graph */
connections: ["avery", "kali", "lexi", "jewelz", "kate"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "social",
pairing: "medium",
schedule: {
anchor: { weekday: "Club", weekend: "Club" },
weekday: ["Club", "Cinema", "Electronics Store"],
weekend: ["Arcade", "Club", "Cinema"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "flashpoint",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- ALISON --- */
<<set $alison = {
var: "alison",
name: "Alison",
group: "Town Folks",
actress: "Alison Tyler",
description: "Alison is the owner of the gym, a sleek, modern space she built from the ground up. In her late 20s, she's the youngest gym owner in town and she's proud of it — confident, charismatic, and always networking, she knows how to work a room and charm a client. She's a natural businesswoman, but also genuinely passionate about fitness and helping people reach their goals. Alison is warm and approachable, with a magnetic energy that draws people in, but she also has a sharp eye for detail and doesn't let things slide. Despite her success, she's down-to-earth — she still works the front desk, still trains clients, and still cleans the equipment herself when her staff is short-handed.",
/* Social Graph */
connections: ["leah", "abella", "alina", "nicole"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "restless",
pairing: "medium",
schedule: {
anchor: { weekday: "Gym", weekend: "Gym" },
weekday: ["Gym", "Dormitory Hall"],
weekend: ["Dormitory Hall", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "normal",
arrested: false,
captiveDays: 0,
captive: false
}>>/* =========================================================================
G7: PUBLIC FIGURES
Members: Angel, Jane, Ember, Jessa, Keisha, Nicole, Lily
========================================================================= */
/* --- ANGEL --- */
<<set $angel = {
var: "angel",
name: "Angel",
group: "Public Figures",
actress: "Angel Youngs",
description: "Detective Angel is sharp, methodical, and deeply suspicious of everyone. She's been on the force long enough to know that people are capable of terrible things, and she trusts evidence more than testimony. She works cold cases in her spare time because she can't let go of the unsolved ones. She's heard rumors of strange occurrences around town but hasn't found proof—yet.",
/* Social Graph */
connections: ["ember", "jane", "leda", "keisha", "jessa"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Police Station", weekend: "Police Station" },
weekday: ["Police Station", "Cafeteria"],
weekend: ["Police Station"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "authority",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- JANE --- */
<<set $jane = {
var: "jane",
name: "Jane",
group: "Public Figures",
actress: "Molly Jane",
description: "Officer Jane is the boots-on-the-ground presence in town—friendly, approachable, and genuinely invested in keeping people safe. She's the kind of cop who knows the local kids by name and checks on elderly residents during heat waves. She's not naive; she's seen bad things. But she chooses to focus on the good because someone has to.",
/* Social Graph */
connections: ["angel", "ember", "keisha", "jessa", "megan", "nicole", "lily", "winter"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Police Station", weekend: "Police Station" },
weekday: ["Police Station", "Cafeteria", "Courthouse"],
weekend: ["Police Station", "Courthouse"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "authority",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- EMBER --- */
<<set $ember = {
var: "ember",
name: "Ember",
group: "Public Figures",
actress: "Ember Snow",
description: "Chief Ember has run the station for over a decade. She's pragmatic, efficient, and carries the weight of every unsolved case like stones in her pockets. She doesn't show emotion because emotion clouds judgment. She's heard the whispers about strange things—people acting wrong, animals found dead in odd places—but without evidence, she can't act. She's waiting for the other shoe to drop.",
/* Social Graph */
connections: ["angel", "jane", "nicole", "keisha", "jessa", "veruca"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "homebody",
pairing: "low",
schedule: {
anchor: { weekday: "Police Station", weekend: "Police Station" },
weekday: ["Police Station", "Courthouse"],
weekend: ["Police Station"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "authority",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- JESSA --- */
<<set $jessa = {
var: "jessa",
name: "Jessa",
group: "Public Figures",
actress: "Jessa Rhodes",
description: "Jessa is calm, collected, and always dressed like she's about to win an argument. She is Winter's senior and the most capable of the lawyers of the courthouse. She's seen every kind of case and isn't easily surprised, but there's a weariness behind her eyes — the kind that comes from knowing too much about how people really are.",
/* Social Graph */
connections: ["angel", "jane", "nicole", "keisha", "ember", "winter"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Courthouse", weekend: "Courthouse" },
weekday: ["Police Station", "Courthouse"],
weekend: ["Police Station", "Courthouse", "Spa"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "authority",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- KEISHA --- */
<<set $keisha = {
var: "keisha",
name: "Keisha",
group: "Public Figures",
actress: "Keisha Grey",
description: "In her mid-thirties, Keisha works with the local government, often seen in the square overseeing events, checking permits, or talking with citizens. Practical, organized, and outspoken, she has little patience for nonsense, but she also has a genuine desire to see the community thrive. She has a sharp eye for detail and knows nearly everyone in town. Though serious at work, she softens around young people, offering advice or guidance when she thinks they need it.",
/* Social Graph */
connections: ["angel", "jane", "nicole", "jessa", "ember", "uma", "kailey", "savannah", "megan", "kyler"],
met: false,
meetingMethod: "solo",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "medium",
schedule: {
anchor: { weekday: "Town Hall", weekend: "Town Square" },
weekday: ["Office", "Courthouse"],
weekend: ["Spa", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "authority",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- NICOLE --- */
<<set $nicole = {
var: "nicole",
name: "Nicole",
group: "Public Figures",
actress: "Nicole Aniston",
description: "A confident and charismatic leader, Mayor Nicole is a woman in her late 30s with a warm, engaging smile. Her bright blue eyes sparkle with intelligence and passion for her work, and she carries herself with an air of authority and poise. She is always impeccably dressed in professional attire, exuding an sense of confidence and capability.",
/* Social Graph */
connections: ["angel", "jane", "jessa", "keisha", "ember", "alison", "carolina", "lily", "megan", "stella"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "busy",
pairing: "medium",
schedule: {
anchor: { weekday: "Town Hall", weekend: "Town Hall" },
weekday: ["Town Hall"],
weekend: ["Spa", "Gym"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "authority",
arrested: false,
captiveDays: 0,
captive: false
}>>
/* --- LILY --- */
<<set $lily = {
var: "lily",
name: "Lily",
group: "Public Figures",
actress: "Lily Rader",
description: "A friendly and helpful young woman, Secretary Lily is in her early 20s with long blonde hair and a warm, welcoming smile. Her bright green eyes are always eager to help, and she has a gentle, caring demeanor that puts everyone at ease. She is often dressed in colorful, fashionable clothing that reflects her bubbly personality, and she has a way of making everyone feel like they're the most important person in the room.",
/* Social Graph */
connections: ["angel", "jane", "nicole", "keisha", "ember", "lily", "jessa", "megan", "kendra", "shazia", "autumn"],
met: false,
meetingMethod: "group",
/* Roaming Logic */
roamTrait: "routine-bound",
pairing: "low",
schedule: {
anchor: { weekday: "Town Hall", weekend: "Town Hall" },
weekday: ["Library"],
weekend: ["Library", "Restaurant"]
},
/* Infection Stats */
corr: 0,
infected: false,
breed: false,
trait: "influential",
arrested: false,
captiveDays: 0,
captive: false
}>><<nobr>>
<<set _mChar = State.variables[$meetingTarget]>>
<<set _method = _mChar ? _mChar.meetingMethod : null>>
<<if !_mChar or !_method>>
<<goto "TownHub">>
<</if>>
<<if _method is "solo">>
<<set State.variables[$meetingTarget].met = true>>
<<run window.rollNewGoals()>>
<<set $metToday = true>>
<<goto "SoloMeetingScenes">>
<<elseif _method is "group">>
<<set _gPair = $groupMeetings.find(g => g.members.includes($meetingTarget))>>
<<if _gPair>>
<<for _pid range _gPair.members>>
<<set State.variables[_pid].met = true>>
<</for>>
<</if>>
<<run window.rollNewGoals()>>
<<set $metToday = true>>
<<goto "GroupMeetingScenes">>
<<elseif _method is "contact">>
/* The introducer is whoever first qualified — locked in permanently by
getContactIntroducer(). No co-location requirement. */
<<set $meetingIntroducer = window.getContactIntroducer($meetingTarget)>>
<<if $meetingIntroducer>>
<<set State.variables[$meetingTarget].met = true>>
/* Duos are met together */
<<set _duo = window.CONTACT_DUOS[$meetingTarget]>>
<<if _duo and State.variables[_duo.partner]>>
<<set State.variables[_duo.partner].met = true>>
<</if>>
<<run window.rollNewGoals()>>
<<set $metToday = true>>
<<goto "ContactMeetingScene">>
<<else>>
<<goto "TownHub">>
<</if>>
<</if>>
<</nobr>><<nobr>>
/* ─────────────────────────────────────────────────────────────────────────
SOLO MEETING ROUTER
The scene bodies were one 1,328-line passage; they are now split across
SoloMeetingScenes-A and SoloMeetingScenes-B. This passage owns the shared
header, the fallback and the first-impression block, and includes the
correct half. Adding a new girl = add her id to the list below and write
her branch in that half.
───────────────────────────────────────────────────────────────────────── */
<<set _mc = State.variables[$meetingTarget]>>
<<if !_mc>><<goto "TownHub">><</if>>
<<set _img = window.getEventImagePath(_mc.name)>>
<<set _groupA = ["maya","alex","ashly","caprice","blake","haley","ember","angel","jane","avi","yulia","nancy","skylar","kate","anya","shazia"]>>
<<set _half = _groupA.includes($meetingTarget) ? "SoloMeetingScenes-A" : "SoloMeetingScenes-B">>
<</nobr>>
<div style="padding:0 24px 32px;">
/* ── HEADER ── */
<div style="text-align:center; margin-bottom:28px; padding-bottom:20px; border-bottom:2px solid #9c27b0;">
<img @src="_img" style="width:320px; max-width:70%; border-radius:10px; border:2px solid #9c27b0; display:block; margin:0 auto 14px;">
<h2 style="margin:0; color:#bd59ff; text-transform:uppercase; letter-spacing:0.05em; font-size:1.6em;"><<print _mc.name>></h2>
<div style="color:#666; font-size:0.82em; text-transform:uppercase; letter-spacing:0.1em; margin-top:4px;">First Meeting</div>
<<if _mc.group>>
<span style="display:inline-block; background:#1a0030; border:1px solid #6a0dad; border-radius:20px; padding:4px 14px; font-size:0.78em; color:#bd59ff; letter-spacing:0.06em; margin-top:10px;">
<<print window.getGroupLabel(_mc.group)>>
</span>
<</if>>
</div>
/* ── DIALOGUE ── */
<<include _half>>
/* ── FIRST IMPRESSION ── */
<<if _mc.description>>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; border-radius:0 6px 6px 0; padding:14px 18px; margin:24px 0; font-size:0.9em; color:#ccc; font-style:italic; line-height:1.6;">
<div style="color:#bd59ff; font-size:0.8em; font-style:normal; font-weight:bold; text-transform:uppercase; letter-spacing:0.08em; margin-bottom:8px;">First Impression</div>
<<print _mc.description>>
</div>
<</if>>
<p style="color:#666; font-size:0.85em; margin-top:24px; text-align:center;">
You've met <strong style="color:#bd59ff;"><<print _mc.name>></strong>.
</p>
</div>
<<nobr>>
<<set $meetingTarget = null>>
<<set $meetingIntroducer = null>>
<<set $groupMeetingRollLoc = "">>
<</nobr>>
[[Return to Town (1)|TownHub]]<<nobr>>
<<set _mc = State.variables[$meetingTarget]>>
<<set _intro = $meetingIntroducer ? State.variables[$meetingIntroducer] : null>>
<<set _iname = _intro ? _intro.name : "someone">>
<<set _duo = window.CONTACT_DUOS[$meetingTarget]>>
<<set _partner = _duo ? State.variables[_duo.partner] : null>>
<</nobr>>
<div style="padding:0 24px 32px;">
<div style="text-align:center; margin-bottom:24px; padding-bottom:14px; border-bottom:2px solid #9c27b0;">
<h2 style="margin:0; color:#bd59ff; text-transform:uppercase; letter-spacing:0.05em; font-size:1.5em;">Introduction</h2>
<<if _intro>>
<div style="color:#666; font-size:0.8em; text-transform:uppercase; letter-spacing:0.1em; margin-top:5px;">through <<print _iname>></div>
<</if>>
</div>
/* ── PORTRAITS ── */
<div style="display:flex; gap:16px; justify-content:center; align-items:flex-end; flex-wrap:wrap; margin-bottom:24px;">
<div style="text-align:center; flex:1; min-width:120px; max-width:250px;">
<img @src="window.getEventImagePath(_mc.name)" style="width:100%; border-radius:8px; border:2px solid #bd59ff;">
<div style="color:#bd59ff; font-size:0.88em; margin-top:8px; font-weight:bold;"><<print _mc.name>></div>
</div>
<<if _partner>>
<div style="text-align:center; flex:1; min-width:120px; max-width:250px;">
<img @src="window.getEventImagePath(_partner.name)" style="width:100%; border-radius:8px; border:2px solid #bd59ff;">
<div style="color:#bd59ff; font-size:0.88em; margin-top:8px; font-weight:bold;"><<print _partner.name>></div>
</div>
<</if>>
</div>
/* ══════════════════════════════════════════════════════════════════════
DIALOGUE
Every contact girl has her own scene. The introducer is named through
the _iname temporary, so the same scene works no matter who unlocked her.
══════════════════════════════════════════════════════════════════════ */
<<if $meetingTarget is "chloe">>
You're halfway down the hall when you place her — the girl from <<print _iname>>'s class, the one who gets talked about as //lovely// with no further detail offered.
She spots you looking and, rather than pretending she hasn't, comes over.
<<speech "Chloe">> "You're $name." <</speech>>
<<speech "$name">> "I am." <</speech>>
<<speech "Chloe">> "<<print _iname>> talks about you. A lot, actually. I was starting to think she'd made you up." <</speech>>
She shifts her folder to the other arm and offers a hand, which almost nobody here does.
<<speech "Chloe">> "Chloe." <</speech>>
<<speech "$name">> "What's she been saying?" <</speech>>
<<speech "Chloe">> "Nothing bad. That's sort of the problem — it's all been very glowing and now you have to live up to it." <</speech>>
She says it lightly, and it lands as a joke rather than a test.
<<speech "Chloe">> "For what it's worth I'd already noticed you. You're one of about four people who holds the door on this corridor." <</speech>>
<<speech "$name">> "That's a low bar." <</speech>>
<<speech "Chloe">> "It's a //terrible// bar. I've complained about it. Nothing happened." <</speech>>
The bell goes somewhere above you and she doesn't move for it.
<<speech "Chloe">> "If you ever need someone who actually knows where anything is, that's me. I'm not being nice, I just genuinely can't stand watching people wander." <</speech>>
<<speech "$name">> "Noted." <</speech>>
<<speech "Chloe">> "Good. Tell <<print _iname>> I said you were taller than advertised." <</speech>>
She's already walking backwards toward her class, and she raises the folder in something between a wave and a salute.
<<elseif $meetingTarget is "rae">>
She's leaning against the wall in a way that suggests she's been there long enough to have decided nobody is going to move her.
You've barely registered her before she speaks.
<<speech "Rae">> "You're <<print _iname>>'s." <</speech>>
<<speech "$name">> "I'm my own, mostly." <</speech>>
<<speech "Rae">> "Mm. She described you and I filled in the rest wrong, so this is a bit disappointing." <</speech>>
<<speech "$name">> "What did you fill in?" <</speech>>
<<speech "Rae">> "Something with more of an edge. You look like you return library books on time." <</speech>>
She pushes off the wall, unhurried, and looks you over with the frankness of someone who has decided rudeness is more efficient than politeness.
<<speech "Rae">> "Rae. Before you ask — yes, that Rae, and yes, the detention thing is true, and no, it isn't as interesting as people make it." <</speech>>
<<speech "$name">> "I wasn't going to ask." <</speech>>
<<speech "Rae">> "Everyone asks. You were about four seconds off." <</speech>>
She tilts her head slightly, recalculating.
<<speech "Rae">> "<<print _iname>> doesn't say much about people. She said something about you, though, which is why I've bothered with this entire conversation." <</speech>>
<<speech "$name">> "And?" <</speech>>
<<speech "Rae">> "Undecided. You've got about a week." <</speech>>
She starts to leave and then stops, without turning round, because of course she does.
<<speech "Rae">> "You didn't ask what she said. That's the first interesting thing you've done." <</speech>>
<<elseif $meetingTarget is "ash">>
She's tucked into the corner seat with a notebook angled away from the room, and she has clocked you coming three seconds before you arrive — you can tell, because the notebook is already closed.
<<speech "$name">> "Ash?" <</speech>>
<<speech "Ash">> "…Yeah." <</speech>>
<<speech "$name">> "<<print _iname>> pointed you out. Said I should say hello." <</speech>>
Something shifts in her face — not relief exactly, but the specific relaxation of someone who has been handed a reason to be spoken to.
<<speech "Ash">> "She did?" <</speech>>
<<speech "$name">> "Her exact words were that you're the best writer in the year and nobody knows." <</speech>>
<<speech "Ash">> "That's — she shouldn't say that." <</speech>>
<<speech "Ash">> "She says that to people. I've asked her not to." <</speech>>
She has gone a determined shade of pink and is holding the notebook a fraction tighter.
<<speech "$name">> "Is it true?" <</speech>>
<<speech "Ash">> "…I don't know. Probably not. There are quite a lot of people in the year." <</speech>>
She glances up at you, then away, then — visibly deciding something — back again, and holds it.
<<speech "Ash">> "Sorry. I'm not good at this bit. The start bit." <</speech>>
<<speech "$name">> "You're doing fine." <</speech>>
<<speech "Ash">> "I'm really not, but thank you for saying it." <</speech>>
She turns the notebook over in her hands a couple of times, and then, quietly:
<<speech "Ash">> "You can sit, if you want. I'm not going to talk much. But you can sit." <</speech>>
<<elseif $meetingTarget is "lulu" or $meetingTarget is "molly">>
The cinema lobby smells like burnt sugar and carpet cleaner. Two girls are having what is clearly the continuation of a very long argument beside the poster for something you haven't heard of.
<<speech "Lulu">> "—and //that's// why the ending works, which you would know if you'd been awake for it." <</speech>>
<<speech "Molly">> "I was awake for all of it." <</speech>>
<<speech "Lulu">> "You were asleep by the boat." <</speech>>
<<speech "Molly">> "I was resting my eyes during the boat." <</speech>>
The taller one turns, sees you, and abandons the argument mid-sentence with the ease of someone who does this constantly.
<<speech "Lulu">> "Oh — you're <<print _iname>>'s friend. The one she mentioned." <</speech>>
<<speech "$name">> "That depends what she mentioned." <</speech>>
<<speech "Lulu">> "Only good things, relax. Lulu. That's Molly. We're here every week and we have wildly different opinions about why." <</speech>>
<<speech "Molly">> "I'm here for the company. She's here for the //art//." <</speech>>
<<speech "Lulu">> "It //is// art." <</speech>>
<<speech "Molly">> "It was a film about a shark." <</speech>>
<<speech "Lulu">> "It was a film about //grief//, and there happened to be a shark in it." <</speech>>
Molly looks at you with the flat, patient expression of a woman who has had this exact exchange in this exact lobby many times.
<<speech "Molly">> "She'll do this for another twenty minutes if you let her. You can just walk away, we won't be offended." <</speech>>
<<speech "$name">> "I've got time." <</speech>>
<<speech "Lulu">> "//Thank// you. Finally." <</speech>>
<<speech "Molly">> "Oh no." <</speech>>
<<speech "Lulu">> "Right — Thursdays are the good screenings, Tuesdays are the cheap ones, and if you come on a Saturday you deserve what happens to you." <</speech>>
<<speech "Molly">> "She's not joking about Saturdays." <</speech>>
<<speech "Lulu">> "I have never once joked about Saturdays." <</speech>>
Molly tips her head toward the screens, already moving.
<<speech "Molly">> "Come along one week. Genuinely. She's better company when there's someone new to lecture — I get a night off." <</speech>>
<<elseif $meetingTarget is "madi" or $meetingTarget is "kenzie">>
The arcade is loud in the specific way that makes people shout things they'd normally keep to themselves. Two girls are at the fighting cabinet in the corner, and one of them is losing badly and enjoying it enormously.
<<speech "Madi">> "That wasn't a real hit." <</speech>>
<<speech "Kenzie">> "It was a perfect hit." <</speech>>
<<speech "Madi">> "It was //luck//." <</speech>>
<<speech "Kenzie">> "It was luck three rounds ago. Now it's just a pattern." <</speech>>
The round ends. The one who lost spins on her stool, spots you, and lights up in a way that has nothing to do with the game.
<<speech "Madi">> "Hey — you're <<print _iname>>'s. She said you'd turn up eventually." <</speech>>
<<speech "$name">> "Did she say when?" <</speech>>
<<speech "Madi">> "No, she was very mysterious about it. I assumed she was exaggerating, she usually is." <</speech>>
<<speech "Madi">> "Madi. That's Kenzie. She's the one on the leaderboard, I'm the one who beat her twice last week." <</speech>>
<<speech "Kenzie">> "You beat me twice in eleven months." <</speech>>
<<speech "Madi">> "Twice is twice." <</speech>>
Kenzie hasn't turned round. She's re-feeding the machine with the concentration of someone doing something important.
<<speech "Kenzie">> "Are you any good, or are you going to be another one of her charity cases?" <</speech>>
<<speech "$name">> "I've no idea. I've never played." <</speech>>
That does turn her round.
<<speech "Kenzie">> "Never." <</speech>>
<<speech "$name">> "Never." <</speech>>
<<speech "Kenzie">> "Right. Sit down." <</speech>>
<<speech "Madi">> "Oh, she likes you. That's her voice for liking people." <</speech>>
<<speech "Kenzie">> "It's my voice for a free win." <</speech>>
<<speech "Madi">> "It's both. It's usually both." <</speech>>
Kenzie slides a token across the top of the cabinet toward you without looking, which is apparently how she offers things.
<<speech "Kenzie">> "First one's on the house. After that you owe me, and I do keep count." <</speech>>
<<else>>
<<if _intro>>
<p><<print _iname>> mentioned her, so you introduce yourself. <<print _mc.name>> is warmer about it than you expected — it turns out being vouched for goes a long way.</p>
<<else>>
<p>You strike up a conversation, and it flows easier than you expected. <<print _mc.name>> is warm, engaged — the kind of person who makes you feel like running into her was the best part of the day.</p>
<</if>>
<</if>>
/* ── FIRST IMPRESSION ── */
<<if _mc.description>>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; border-radius:0 6px 6px 0; padding:14px 18px; margin:20px 0; font-size:0.9em; color:#ccc; font-style:italic; line-height:1.6;">
<div style="color:#bd59ff; font-size:0.8em; font-style:normal; font-weight:bold; text-transform:uppercase; letter-spacing:0.08em; margin-bottom:8px;">First Impression</div>
<<print _mc.description>>
</div>
<</if>>
<<if _partner and _partner.description>>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; border-radius:0 6px 6px 0; padding:14px 18px; margin:16px 0; font-size:0.9em; color:#ccc; font-style:italic; line-height:1.6;">
<div style="color:#bd59ff; font-size:0.8em; font-style:normal; font-weight:bold; text-transform:uppercase; letter-spacing:0.08em; margin-bottom:8px;"><<print _partner.name>></div>
<<print _partner.description>>
</div>
<</if>>
<<if _mc.group>>
<div style="text-align:center; margin-bottom:12px;">
<span style="display:inline-block; background:#1a0030; border:1px solid #6a0dad; border-radius:20px; padding:4px 14px; font-size:0.78em; color:#bd59ff; letter-spacing:0.06em;">
<<print window.getGroupLabel(_mc.group)>>
</span>
</div>
<</if>>
<p style="color:#666; font-size:0.85em; margin-top:16px; text-align:center;">
You've met <strong style="color:#bd59ff;"><<print _mc.name>></strong><<if _partner>> and <strong style="color:#bd59ff;"><<print _partner.name>></strong><</if>>.
</p>
</div>
<<nobr>>
<<set $meetingTarget = null>>
<<set $meetingIntroducer = null>>
<</nobr>>
[[Return to Town (1)|TownHub]]<<nobr>>
<<set _mc = State.variables[$meetingTarget]>>
<<set _pair = $groupMeetings.find(g => g.members.includes($meetingTarget))>>
/* Build the list of all members in this group */
<<if _pair>>
<<set _members = _pair.members.map(id => State.variables[id])>>
<<set _metNames = _pair.members.map(id => State.variables[id].name).join(" and ")>>
<<else>>
<<set _members = [_mc]>>
<<set _metNames = _mc.name>>
<</if>>
<</nobr>>
<div style="padding:0 24px 32px;">
/* ── HEADER ── */
<div style="text-align:center; margin-bottom:24px; padding-bottom:16px; border-bottom:2px solid #9c27b0;">
<h2 style="margin:0; color:#bd59ff; text-transform:uppercase; letter-spacing:0.05em; font-size:1.5em;">First Meeting</h2>
</div>
/* ── PORTRAITS (one per group member, regardless of group size) ── */
<div style="display:flex; gap:16px; justify-content:center; align-items:flex-end; flex-wrap:wrap; margin-bottom:24px;">
<<for _gm range _members>>
<div style="text-align:center; flex:1; min-width:120px; max-width:260px;">
<img @src="window.getEventImagePath(_gm.name)" style="width:100%; border-radius:8px; border:2px solid #9c27b0;">
<div style="color:#bd59ff; font-size:0.88em; margin-top:8px; font-weight:bold;"><<print _gm.name>></div>
</div>
<</for>>
</div>
/* ── DIALOGUE ── */
/* --- Laila & Demi (Neighbourhood) --- */
<<if $meetingTarget is "laila" or $meetingTarget is "demi">>
You knock on the familiar door. Laila answers almost immediately, her smile warm and open.
<<speech "laila">>"$name! Come in. I was just about to put the kettle on."<</speech>>
Inside, the house smells like cinnamon and old books. Demi is in the kitchen doorway, camera hanging from her neck, a small box of photos in her hands.
<<speech "demi">>"It's been a while. Is Emily settling in okay?"<</speech>>
<<speech "$name">>"She's doing better."<</speech>>
Demi nods, flipping open the box. Inside are photographs — the street, the garden, the houses at dusk.
<<speech "demi">>"I've been documenting the block. For a project."<</speech>>
She pulls out a photo — your house, evening, the windows warm against the darkening sky.
<<speech "demi">>"You've got good light. The way it hits the front steps."<</speech>>
<<speech "laila">>"She's been at it for weeks. Caught your porch last Tuesday."<</speech>>
Laila slides a cup toward you.
<<speech "laila">>"Sit. You're always welcome here."<</speech>>
Demi settles into a chair across from you, the photo still in her hands.
<<speech "demi">>"If you ever want to just sit. Watch the light change. You know where to find us."<</speech>>
/* --- Athena & Lacy (Cheerleaders) --- */
<<elseif $meetingTarget is "athena" or $meetingTarget is "lacy">>
Practice has just ended. The other cheerleaders are filtering toward the locker rooms when Athena spots you on the track.
<<speech "athena">>"Hey!"<</speech>>
She waves you over like you're old friends. Lacy stands a few feet away, arms crossed, watching.
<<speech "athena">>"Come to admire our athletic prowess?"<</speech>>
<<speech "$name">>"Taking a walk. Didn't realize practice was still going."<</speech>>
<<speech "lacy">>"It's not. Athena's trying to convince me the new pyramid isn't going to kill anyone."<</speech>>
<<speech "athena">>"It's not! We've got it. Almost."<</speech>>
<<speech "lacy">>"Almost isn't good enough."<</speech>>
Lacy's eyes flick to you.
<<speech "lacy">>"You're friends with Isabella. And Blake."<</speech>>
She pauses.
<<speech "lacy">>"And Vanna."<</speech>>
<<speech "$name">>"She is not as bad as many think she is."<</speech>>
<<speech "lacy">>"She's exhausting."<</speech>>
<<speech "$name">>"You're not wrong."<</speech>>
Athena snorts. Lacy almost smiles, finally sitting on the bleachers — not next to you, but closer.
<<speech "lacy">>"You don't seem like the type to put up with her."<</speech>>
<<speech "$name">>"She's not as tough as she pretends."<</speech>>
Lacy looks at you for a long moment.
<<speech "lacy">>"No. She's not."<</speech>>
<<speech "athena">>"Lacy's been working on her solo routine. Won't show anyone until it's perfect."<</speech>>
<<speech "lacy">>"I show you."<</speech>>
<<speech "athena">>"You show me because I threaten to steal your shoes."<</speech>>
Lacy almost laughs. You stand to leave.
<<speech "$name">>"Good luck with the routine. Not that you need it."<</speech>>
She looks up.
<<speech "lacy">>"Maybe next time you can tell me what I'm doing wrong."<</speech>>
/* --- Christie & Gina (Cafeteria) --- */
<<elseif $meetingTarget is "christie" or $meetingTarget is "gina">>
You slip through the side door. The cafeteria is quiet, the lunch rush a distant memory.
<<speech "gina">>"$name!"<</speech>>
Gina is behind the counter, apron on, her face lighting up.
<<speech "gina">>"You're late. Christie said you'd show up."<</speech>>
From the kitchen, the oven door opens.
<<speech "christie">>"If he's late, it's because he was actually doing his homework for once."<</speech>>
Christie emerges with a tray of cookies, still warm.
<<speech "gina">>"These are dangerous."<</speech>>
She grabs one. Christie sets the tray in front of you.
<<speech "christie">>"You know Gina's been practicing her latte art all week."<</speech>>
<<speech "gina">>"I made a leaf. Almost."<</speech>>
She holds up her phone — foam that's vaguely plant-shaped.
<<speech "$name">>"That's... something."<</speech>>
<<speech "gina">>"It's a masterpiece and you know it."<</speech>>
Christie pours coffee into three mugs.
<<speech "christie">>"Gina's been here almost a year now. Still acts like she owns the place."<</speech>>
<<speech "gina">>"I'm establishing dominance. It's a process."<</speech>>
She grins at you.
<<speech "christie">>"She's good with customers, though. Got a way of making people feel welcome."<</speech>>
<<speech "gina">>"That's the job, right? Make people feel like they're somewhere they belong."<</speech>>
/* --- Lily & Nicole (Town Hall) --- */
<<elseif $meetingTarget is "lily" or $meetingTarget is "nicole">>
You push open the heavy doors of the Town Hall. Behind the front desk, a young woman with long blonde hair looks up and beams at you.
<<speech "lily">>"Oh! You're the one from the college. The delivery person."<</speech>>
She stands, smoothing her skirt.
<<speech "lily">>"I'm Lily. I run the front desk. You're here so often I feel like I should know your name by now."<</speech>>
Before you can answer, a door opens behind her. A woman in her late 30s steps out, impeccably dressed, her smile warm and engaging.
<<speech "nicole">>"Lily, who's this?"<</speech>>
<<speech "lily">>"The college delivery person I told you about. The reliable one."<</speech>>
<<speech "nicole">>"Ah. Good."<</speech>>
She walks over, extends her hand.
<<speech "nicole">>"I'm Mayor Nicole. Lily's told me good things about you. Reliable, punctual, doesn't make excuses."<</speech>>
She releases your hand, clasps hers together.
<<speech "nicole">>"I like to know the people who keep this town running. You're one of them now."<</speech>>
Lily beams at you.
<<speech "lily">>"I told you she'd want to meet you."<</speech>>
Nicole laughs.
<<speech "nicole">>"Lily's very good at her job. She knows everyone, remembers everything."<</speech>>
She looks at you.
<<speech "nicole">>"If you ever need anything — a favor, an introduction, someone to vouch for you — you come to me or Lily. We take care of people who take care of us."<</speech>>
<<speech "lily">>"What she said. Seriously. We're always here."<</speech>>
Nicole touches Lily's shoulder.
<<speech "nicole">>"I have a meeting. But it was good to finally meet you."<</speech>>
She heads back through the door, leaving you with Lily.
<<speech "lily">>"See? I told you she was nice."<</speech>>
She sits back down, smiling.
<<speech "lily">>"So. What do you need today?"<</speech>>
/* --- Kenna & Quinn (Real Estate) --- */
<<elseif $meetingTarget is "kenna" or $meetingTarget is "quinn">>
You push open the glass door of the real estate office. The space is modern, well-lit, with property photos lining the walls. Behind a sleek desk, a woman in her mid-40s looks up from her paperwork and smiles warmly.
<<speech "kenna">>"Welcome! You must be the college student I've heard about. The one who runs deliveries around town."<</speech>>
She sets down her pen, gestures for you to come closer.
<<speech "kenna">>"I'm Kenna. I manage this office. It's nice to finally put a face to the name."<</speech>>
From the back office, a younger woman emerges — mid-20s, polished, her smile bright and professional. She's holding a tablet.
<<speech "quinn">>"Kenna, are you stealing my clients again?"<</speech>>
She laughs, extending a hand to you.
<<speech "quinn">>"I'm Quinn. I'm the one who actually sells the properties. Kenna just makes sure I don't mess up the paperwork."<</speech>>
Kenna rolls her eyes, but she's smiling.
<<speech "kenna">>"Quinn's our top agent. She could sell a house to someone who's already living in it."<</speech>>
<<speech "quinn">>"That happened once. And they were very happy with the upgrade."<</speech>>
She turns to you, tilting her head.
<<speech "quinn">>"So. Are you looking for a place? Or just delivering something?"<</speech>>
<<speech "$name">>"Delivery. But the office looks nice."<</speech>>
<<speech "kenna">>"We like it. Busy, but nice."<</speech>>
<<speech "quinn">>"If you ever are looking — or know someone who is — you come to me. I'll take care of you."<</speech>>
She winks. Kenna shakes her head.
<<speech "kenna">>"What she means is, we're always happy to help. You're around town a lot. We like knowing the people we see every day."<</speech>>
Quinn glances at her watch.
<<speech "quinn">>"I have a showing in ten, but it was good meeting you. Seriously. Stop by anytime."<</speech>>
She heads for the door, pausing to look back.
<<speech "quinn">>"Kenna's here more than I am. She's the one who actually knows everything."<</speech>>
Kenna laughs.
<<speech "kenna">>"Go. You'll be late."<</speech>>
Quinn disappears through the door, leaving you with Kenna.
<<speech "kenna">>"She's good at what she does. But I meant what I said — we're always here if you need anything."<</speech>>
She picks up her pen again.
<<speech "kenna">>"And if you ever want to know what's really going on in this town, you know where to find me."<</speech>>
She winks, goes back to her paperwork.
/* --- Jasmine, Katie & Kendra (Restaurant) --- */
<<elseif $meetingTarget is "jasmine" or $meetingTarget is "kendra" or $meetingTarget is "katie">>
The restaurant is quiet between lunch and dinner rush. The smell of herbs and bread lingers in the air. Kendra is at the front, reviewing a clipboard, while Katie wipes down a table and Jasmine leans on the counter, chatting with a customer who's clearly not leaving.
Kendra notices you first.
<<speech "kendra">>"$name. You're here early."<</speech>>
She sets down her clipboard, smiling.
<<speech "kendra">>"Your $family's not in until later. But you're welcome to sit."<</speech>>
Jasmine's head snaps up at the mention of your name, a grin spreading across her face.
<<speech "jasmine">>"Oh! You're Jewelz's $familymale! I've heard so much about you."<</speech>>
She abandons the customer mid-conversation, walking over.
<<speech "jasmine">>"I'm Jasmine. I work here. Your $family is the best — she always covers for me when I mess up orders."<</speech>>
Katie finishes wiping down the table and straightens up.
<<speech "katie">>"Which is often."<</speech>>
She gives you a small, dry smile.
<<speech "katie">>"I'm Katie. I work with Jasmine. I'm the one who fixes the orders she messes up."<</speech>>
<<speech "jasmine">>"She's joking. Mostly. She's actually really nice."<</speech>>
Jasmine nudges Katie, who rolls her eyes but there's no real irritation there.
Kendra steps forward.
<<speech "kendra">>"And I'm Kendra. I own this place."<</speech>>
She gestures around the room.
<<speech "kendra">>"You've been here plenty of times. But you're always in and out. You should stay sometime. Eat. Relax. Let us take care of you."<</speech>>
<<speech "jasmine">>"We're good at that. Taking care of people."<</speech>>
Katie nods.
<<speech "katie">>"We are. Even if Jasmine gets the order wrong, she'll make you feel good about it."<</speech>>
<<speech "kendra">>"What she means is, you're family. Jewelz is family. That makes you family."<</speech>>
She picks up her clipboard.
<<speech "kendra">>"Now, since you're here, you want something to drink? On the house."<</speech>>
/* --- Megan, Kyler & Savannah (Internship Office) --- */
<<elseif $meetingTarget is "megan" or $meetingTarget is "kyler" or $meetingTarget is "savannah">>
The office is modern but lived-in — plants on the windowsill, a kettle on a side table, papers stacked neatly on desks. A woman in her late 30s looks up from her computer as you walk in, her smile warm and welcoming.
<<speech "megan">>"$name! Right on time."<</speech>>
She stands, gesturing around the office.
<<speech "megan">>"Welcome to your first day. I'm Megan. I'll be supervising your internship."<</speech>>
From across the room, a young woman with bright eyes and an easy grin waves.
<<speech "kyler">>"Hey! You're the new intern!"<</speech>>
She's already up and walking over, hand extended.
<<speech "kyler">>"I'm Kyler. I've been here for a few weeks now. Megan's been putting me to work."<</speech>>
She laughs, warm and easy.
<<speech "kyler">>"Don't worry, she's not as scary as she looks."<</speech>>
Megan raises an eyebrow.
<<speech "megan">>"I'm not scary at all. I'm encouraging."<</speech>>
Kyler grins.
<<speech "kyler">>"That's what she says. But then she gives you three projects and a deadline."<</speech>>
A third woman approaches — poised, thoughtful, carrying a notebook.
<<speech "savannah">>"She's not wrong. But you'll learn a lot. That's the trade-off."<</speech>>
She offers a polite smile.
<<speech "savannah">>"I'm Savannah. I've been interning here for a few months. If you need help figuring anything out, I'm happy to show you the ropes."<</speech>>
Megan gestures to a desk.
<<speech "megan">>"That's yours. Kyler and Savannah will help you get settled."<</speech>>
<<speech "kyler">>"And we'll make sure you actually enjoy it."<</speech>>
She winks.
<<speech "savannah">>"She means we'll take you out for coffee when Megan's not looking."<</speech>>
Megan laughs.
<<speech "megan">>"I'll pretend I didn't hear that. Welcome aboard, $name."<</speech>>
/* --- Momo, Autumn, Stella & Caitlyn (Hotel) --- */
<<elseif $meetingTarget is "momo" or $meetingTarget is "autumn" or $meetingTarget is "stella" or $meetingTarget is "caitlyn">>
The hotel lobby is grand but quiet — polished marble, soft lighting, the faint sound of piano music. Caitlyn is behind the front desk, her practiced smile firmly in place, while Stella passes by with a cart of fresh towels.
You're waiting near the elevator when Autumn breezes in, sunglasses on, phone in hand, effortlessly magnetic. She pauses when she spots you.
<<speech "autumn">>"You're new."<</speech>>
She lowers her sunglasses, appraising you.
<<speech "autumn">>"I don't usually notice people. But you've got that look. The one that says you're not here for the décor."<</speech>>
She glances at the front desk.
<<speech "autumn">>"Caitlyn's been running this place for years. You'd think she'd smile more, but she's got the whole 'I'm over it' thing down."<</speech>>
Caitlyn overhears, rolling her eyes but not looking up from her screen.
<<speech "caitlyn">>"I smile when I have a reason to, Autumn."<</speech>>
Autumn laughs, smooth and practiced.
<<speech "autumn">>"That's the most you've gotten out of her in weeks. Congratulations."<</speech>>
From the corner, Stella passes by with her cart, glancing at you with a quiet, knowing look.
<<speech "stella">>"Don't let them scare you off. They're all bark."<</speech>>
She continues past, not slowing down.
A woman steps out of the elevator — elegant, composed, perfectly dressed. Momo looks at you, then at the group.
<<speech "momo">>"You're gathering quite the audience."<</speech>>
She walks toward the front desk, her heels clicking softly.
<<speech "momo">>"I'm Momo. I stay here often. And I have a feeling you'll be staying in this lobby more than you planned."<</speech>>
Caitlyn finally looks up.
<<speech "caitlyn">>"What she means is, people who stay here tend to get pulled into the orbit."<</speech>>
She sighs.
<<speech "caitlyn">>"I'm Caitlyn. I run this place. Or I try to."<</speech>>
Autumn gestures around.
<<speech "autumn">>"Welcome to this hotel. Where everyone has a story, and most of them are interesting. Usually."<</speech>>
Stella passes by again, slower this time, offering you the smallest nod as she goes — a quiet acknowledgment that she's seen you, and she's keeping an eye out.
/* --- Adria, Jade & Gabbie (Student Council) --- */
<<elseif $meetingTarget is "adria" or $meetingTarget is "jade" or $meetingTarget is "gabbie">>
The student council office is small but organized — posters on the walls, a whiteboard covered in event plans, stacks of papers on every surface. Adria is at the desk, reviewing a list. Gabbie is sprawled in a chair, scrolling through her phone. Jade is at the whiteboard, adding to a chart.
Adria looks up when you walk in, a familiar smile crossing her face.
<<speech "adria">>"$name. Good timing. We need your opinion on something."<</speech>>
She gestures to the whiteboard.
<<speech "adria">>"Spring formal layout. Gabbie thinks we should move the photo booth, but Jade says it'll block the fire exit."<</speech>>
Gabbie doesn't look up from her phone.
<<speech "gabbie">>"It won't block the fire exit if people aren't using it as a fire exit."<</speech>>
She finally glances at you.
<<speech "gabbie">>"Tell her I'm right."<</speech>>
Jade doesn't turn from the whiteboard.
<<speech "jade">>"Tell him I'm right. And that he owes me from last week when he said he'd help with the decorations and disappeared."<</speech>>
She looks over her shoulder at you, one eyebrow raised.
<<speech "jade">>"I haven't forgotten."<</speech>>
<<speech "$name">>"I got pulled away."<</speech>>
<<speech "jade">>"You always get pulled away."<</speech>>
Adria sets down her pen, leaning back.
<<speech "adria">>"You're the only person we trust to give an honest answer, $name. That's why you're the unofficial fourth member."<</speech>>
Gabbie grins.
<<speech "gabbie">>"You don't get a title or a key to the office, but you get our gratitude."<</speech>>
Jade turns fully now, marker in hand.
<<speech "jade">>"And we never let you forget it."<</speech>>
She taps the whiteboard.
<<speech "jade">>"Now. Fire exit or no fire exit?"<</speech>>
/* --- Leda, Lexi & Avery (Club) --- */
<<elseif $meetingTarget is "leda" or $meetingTarget is "lexi" or $meetingTarget is "avery">>
The club is still quiet, early evening, before the crowd arrives. Neon lights flicker across the empty dance floor. Behind the bar, a woman in her mid-twenties wipes down the counter with practiced ease. In the DJ booth, another woman tests a track, nodding along.
You approach the bar. The bartender looks up, a playful glint in her eyes.
<<speech "lexi">>"You're early. Club doesn't wake up for another hour."<</speech>>
She sets down the rag, leaning on the counter.
<<speech "lexi">>"I'm Lexi. I run this bar. You look like you're waiting for someone, or you're lost. Which is it?"<</speech>>
From the DJ booth, a voice cuts through.
<<speech "leda">>"He's not lost. He's got that look."<</speech>>
She walks over, headphones around her neck, a grin on her face.
<<speech "leda">>"The look that says 'I'm here for the vibe, not the crowd.' I respect that."<</speech>>
She leans against the bar next to you.
<<speech "leda">>"I'm Leda. I make the music. Lexi makes the drinks. We're the reason this place works."<</speech>>
Lexi rolls her eyes, but she's smiling.
<<speech "lexi">>"We're the reason this place stays open. There's a difference."<</speech>>
From behind you, a voice — smooth, confident.
<<speech "avery">>"And I'm the reason people actually show up."<</speech>>
A woman in her late twenties approaches, glamorous and magnetic, a knowing smile on her lips.
<<speech "avery">>"I'm Avery. I'm a regular. And I've seen you around."<</speech>>
She studies you, curious.
<<speech "avery">>"You don't dance, do you?"<</speech>>
<<speech "$name">>"Not usually."<</speech>>
She laughs, light and musical.
<<speech "avery">>"We'll fix that."<</speech>>
She turns to Lexi.
<<speech "avery">>"Get him a drink. On me."<</speech>>
Lexi raises an eyebrow.
<<speech "lexi">>"Is he even old enough?"<</speech>>
<<speech "avery">>"Then get him something boring. Just make him feel included."<</speech>>
She looks at you, her smile softening just a fraction.
<<speech "avery">>"Welcome to the club, $name. Try not to get lost."<</speech>>
Leda laughs.
<<speech "leda">>"Too late. He's already part of the chaos."<</speech>>
/* --- Aidra, Ariana & Harley (Pool) --- */
<<elseif $meetingTarget is "aidra" or $meetingTarget is "ariana" or $meetingTarget is "harley">>
The pool is humid and bright, the smell of chlorine hanging in the air. Aidra stands at the edge, clipboard in hand, her sharp eyes scanning the water. A few students are doing laps, but two of them have paused near the shallow end.
Harley is the first to notice you, waving enthusiastically from the water.
<<speech "harley">>"Hey! You're actually here! I thought you were skipping today."<</speech>>
She swims to the edge, resting her arms on the tiles.
<<speech "harley">>"You're late. Aidra's about to make us do laps until we regret being born."<</speech>>
Aidra glances up from her clipboard, a hint of dry amusement in her voice.
<<speech "aidra">>"I don't make students regret being born. I make them regret being late."<</speech>>
She looks at you, unimpressed but not angry.
<<speech "aidra">>"Get changed. You've missed the warm-up. That means extra laps."<</speech>>
Harley grins.
<<speech "harley">>"Told you."<</speech>>
From the other end of the pool, Ariana surfaces, her strokes smooth and controlled. She doesn't smile, just offers a brief nod of acknowledgment.
<<speech "ariana">>"You're in my lane. I'll move."<</speech>>
She says it flatly, not unfriendly, just practical.
<<speech "harley">>"She's not mad. She just doesn't talk much. But she's the fastest swimmer here, so try to keep up."<</speech>>
Ariana looks at Harley, then back at you.
<<speech "ariana">>"I don't mind if you're slow. Just don't get in the way."<</speech>>
She turns and pushes off the wall, cutting through the water with practiced precision.
Aidra sets her clipboard down.
<<speech "aidra">>"Twenty laps to start. Then we'll talk about your form."<</speech>>
She pauses.
<<speech "aidra">>"And try to keep up with Ariana. She's your best teacher."<</speech>>
Harley splashes water at you playfully.
<<speech "harley">>"You heard her. Get in here. I'll race you to the other end."<</speech>>
/* --- Fallback --- */
/* --- Alison, Leah & Abella (The Gym) --- */
<<elseif $meetingTarget is "alison" or $meetingTarget is "leah" or $meetingTarget is "abella">>
The gym is bright and smells of rubber matting and citrus cleaner. A woman behind the front desk is wiping down a stack of weight collars by hand, sleeves pushed up, and she clocks you the second the door swings.
<<speech "alison">>"New face. Good."<</speech>>
She comes round the desk rather than talking over it.
<<speech "alison">>"Alison. This is mine — the building, the equipment, the terrible playlist. Complaints come to me and I actually read them."<</speech>>
<<speech "$name">>"You clean the kit yourself?"<</speech>>
<<speech "alison">>"Two of my staff are off. And I'd rather do it than explain how I want it done."<</speech>>
Behind her, a very tall girl is going along the bench row lifting towels one at a time and putting them back down.
<<speech "leah">>"Has anyone seen a blue —"<</speech>>
<<speech "alison">>"No."<</speech>>
<<speech "leah">>"You don't know what I was going to say."<</speech>>
<<speech "alison">>"It's Tuesday. It's the water bottle."<</speech>>
<<speech "leah">>"…It might be the water bottle."<</speech>>
She abandons the towels entirely and comes over at speed, hand already out.
<<speech "leah">>"Leah. Basketball. Hi. Are you joining? You should join, it's really —"<</speech>>
She shakes your hand with considerably more force than necessary and does not finish the sentence.
<<speech "leah">>"Sorry, what was your name?"<</speech>>
<<speech "$name">>"$name."<</speech>>
<<speech "leah">>"$name. Right. Yes."<</speech>>
<<speech "alison">>"She'll lose that in about ninety seconds."<</speech>>
<<speech "leah">>"I will not."<</speech>>
Over at the far rack a third girl is working through a set with her hood up, back to all of this. She hasn't acknowledged the conversation once.
<<speech "alison">>"Abella. Come and say hello."<</speech>>
<<speech "abella">>"I'm mid-set."<</speech>>
<<speech "alison">>"You've been mid-set for forty minutes."<</speech>>
She racks the bar and comes over unhurried, pulling one earbud out. She does not offer a hand.
<<speech "abella">>"Hi."<</speech>>
<<speech "$name">>"Hi."<</speech>>
<<speech "abella">>"That's it. That's the whole thing."<</speech>>
<<speech "leah">>"She's like this with everyone. It's not you."<</speech>>
<<speech "abella">>"It's a bit you."<</speech>>
<<speech "leah">>"That's fair."<</speech>>
Alison pulls a form off the stack and slides it across the desk.
<<speech "alison">>"Sign this and you're on the system. Nothing sinister — I need to know who's in the building if the alarm goes."<</speech>>
<<speech "leah">>"Oh — do you know Alina? You should meet Alina, she's brilliant, she works —"<</speech>>
<<speech "alison">>"She introduced you to him. Last week. In this room."<</speech>>
<<speech "leah">>"Did she?"<</speech>>
<<speech "alison">>"You were holding a cone."<</speech>>
<<speech "leah">>"…I do remember a cone."<</speech>>
She says this as though it settles the matter, and turns back to you with total sincerity.
<<speech "leah">>"Anyway come at six, six is the best. Nobody's here at six except me and it gets a bit —"<</speech>>
<<speech "abella">>"I'm here at six."<</speech>>
<<speech "leah">>"You're here at //eleven//. At night. Like a burglar."<</speech>>
<<speech "abella">>"Because it's empty at eleven."<</speech>>
<<speech "leah">>"Right, yeah. Come at eleven, it's much quieter."<</speech>>
<<speech "alison">>"Leah."<</speech>>
<<speech "leah">>"What?"<</speech>>
Alison doesn't answer. Leah frowns at the middle distance for a second, decides it doesn't matter, and beams at you again.
You finish the form. She reads it upside down over your shoulder with no shame whatsoever.
<<speech "leah">>"That's not what I had. I had something with an M."<</speech>>
Abella has already turned to go, hood up, earbud halfway in — and then she stops.
<<speech "abella">>"You held the door for the woman with the pram on your way in."<</speech>>
<<speech "$name">>"…Okay."<</speech>>
<<speech "abella">>"Most people here don't. That's all."<</speech>>
She walks back to the rack without waiting for a reply.
<<speech "alison">>"That was about nine hundred words for her. You should feel flattered."<</speech>>
Behind you, from somewhere near the towel bench, there is a small triumphant noise.
<<speech "leah">>"Found it! It was in the —"<</speech>>
<<speech "alison">>"Don't tell me."<</speech>>
<<speech "leah">>"It was in the ice machine."<</speech>>
<<speech "alison">>"I said don't tell me."<</speech>>
<<else>>
You find yourself introduced to a group.
<</if>>
<p style="color:#666; font-size:0.85em; margin-top:24px; text-align:center;">
You've met <strong style="color:#bd59ff;"><<print _metNames>></strong>.
</p>
</div>
<<nobr>>
<<set $meetingTarget = null>>
<<set $meetingIntroducer = null>>
<<set $groupMeetingRollLoc = "">>
<</nobr>>
[[Return to Town (1)|TownHub]]<<nobr>>
<<set _actLoc = $currentLocation>>
<<set _def = window.ACTIVITY_DEFS ? window.ACTIVITY_DEFS[_actLoc] : null>>
<<set _actName = _def ? (_def.icon + " " + _def.name) : "Activity">>
<<set _attendees = window.buildActivityAttendees(_actLoc)>>
/* Name the activity itself so the infection register can say "at the Hotel
Gala" rather than the generic "At a gathering". _def is the ACTIVITY_DEFS
entry resolved two lines above. */
<<set _actEvent = _def ? ("the " + _def.name) : ("an activity at " + _actLoc)>>
<<set _results = window.resolvePartyMingle(_attendees, _actLoc, _actEvent, "activity")>>
<<set _corrupt = []>>
<<for _id range _attendees>>
<<if State.variables[_id].corr >= 25>><<run _corrupt.push(_id)>><</if>>
<</for>>
/* Limit video list to girlsPerScene */
<<set _videoList = _attendees.filter(id => State.variables[id].corr >= 25).slice(0, ($settings && $settings.girlsPerScene) ? $settings.girlsPerScene : 4)>>
<</nobr>>
<div style="text-align:center; margin-bottom:20px; border-bottom:2px solid #9c27b0; padding-bottom:10px;">
<h1 style="margin:0; color:#bd59ff;"><<print _actName>></h1>
<div style="color:#aaa; font-size:0.9em; margin-top:4px;">
<<print _actLoc>> · Parasites: <span style="color:#bd59ff; font-weight:bold;">$parasite</span>
· Infected: <span style="color:<<if window.hivemindFull()>>#ff5555<<else>>#bd59ff<</if>>;">
<<print window.getHivemindLoad()>> / <<print $hivemindCap>>
</span>
</div>
</div>
<<if _videoList.length > 0>>
<div style="background:#000; padding:10px; border:1px solid #333; border-radius:8px; margin-bottom:20px;">
<<GroupVideos _videoList>>
</div>
<<else>>
<div style="text-align:center; color:#555; font-style:italic; padding:15px; background:#111; border-radius:6px; margin-bottom:20px;">
Nothing out of the ordinary... yet.
</div>
<</if>>
<<if _results.length > 0>>
<div style="background:#1a1a1a; border:1px solid #9c27b0; border-radius:6px; padding:12px; margin-bottom:20px;">
<strong style="color:#bd59ff; font-size:0.9em; text-transform:uppercase; display:block; margin-bottom:8px;">Events</strong>
<ul style="margin:0; padding-left:18px; color:#ccc; font-size:0.9em;">
<<for _msg range _results>><li style="margin-bottom:3px;"><<print _msg>></li><</for>>
</ul>
</div>
<</if>>
<div style="display:flex; flex-wrap:wrap; gap:10px; justify-content:flex-start; margin-bottom:20px;">
<<for _id range _attendees>>
<<set _char = State.variables[_id]>>
<<capture _id>>
<<set _girlCap = window.getCorrCap ? window.getCorrCap(_id) : 25>>
<<set _atCap = _char.infected && _char.corr >= _girlCap && _char.corr < 100>>
<div style="text-align:center; width:140px;">
<<if _char.met>>
<<set _img = window.getEventImagePath(_char.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; position:relative; border:2px solid ' + (_atCap ? '#bd59ff' : 'transparent') + ';'">
<div class="loc-bar-container">
<div class="loc-bar-fill" @style="'width:' + _char.corr + '%'"></div>
</div>
<<if _atCap>>
<div style="position:absolute; top:3px; right:3px; background:#bd59ff; color:#fff; font-size:0.58em; font-weight:bold; padding:2px 4px; border-radius:3px;">CAP</div>
<</if>>
</div>
<div style="font-size:0.85em; font-weight:bold; color:#ccc; margin-top:4px;"><<charLink _id>></div>
<div style="font-size:0.75em; margin-top:2px;">
<<if _char.breed>><span style="color:#ff5959;">♥ Bred</span>
<<elseif _char.infected>><span style="color:#bd59ff;">☣ Infected</span>
<<else>><span style="color:#444;">Healthy</span>
<</if>>
</div>
<<elseif $upgrades && $upgrades.revealPortraits>>
<<set _img = window.getPortraitPath(_char.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; filter:grayscale(1); opacity:0.3;'"></div>
<div style="font-size:0.85em; color:#333; margin-top:4px;">???</div>
<<else>>
<div style="width:140px; height:210px; background:#111; border-radius:6px; display:flex; align-items:center; justify-content:center; border:1px solid #222;">
<span style="font-size:3em; color:#444;">?</span>
</div>
<div style="font-size:0.85em; color:#444; margin-top:4px;">???</div>
<</if>>
</div>
<</capture>>
<</for>>
</div>
/* ── BRED CHECK ── */
<<set _newlyBred = []>>
<<for _bid range _attendees>>
<<set _bc = State.variables[_bid]>>
/* Breeding: corruption 75 or more. The old rule ALSO demanded she be at her
personal cap, which made breeding impossible for most of the late game —
once you bought Universal Threshold III (or broke her cap) the ceiling was
100, so a devoted girl at 75, 80 or 90 could never be bred. Only a girl
sitting exactly at her cap qualified, which is why it fired sometimes and
not others. 75 is the Devoted threshold and is the intended gate. */
<<if _bc.corr >= 75 and !_bc.breed>>
<<set State.variables[_bid].breed = true>>
<<run _newlyBred.push(_bc.name)>>
<</if>>
<</for>>
<<if _newlyBred.length > 0>>
<div style="background:#1a0010; border:1px solid #ff5959; border-radius:6px; padding:12px; margin-bottom:20px; text-align:center;">
<strong style="color:#ff5959; font-size:0.95em; display:block; margin-bottom:8px;">♥ Bred This Activity</strong>
<<for _bn range _newlyBred>>
<div style="color:#ff8888; font-size:0.9em; margin-bottom:2px;"><<print _bn>> has been bred.</div>
<</for>>
</div>
<</if>>
<div style="margin-top:24px; text-align:center; display:flex; gap:12px; justify-content:center; flex-wrap:wrap;">
<<button "Sleep">><<goto "DayEnd">><</button>>
</div>/* Explicit destination rather than a back macro. `back` REWINDS the variable
state to before this passage was entered instead of navigating, so anything
done here is discarded -- and with no history it cannot resolve at all. */
[[← Back to the Hub|TownHub]]
<h1 style="text-align:center; color:#bd59ff; margin-bottom:4px;">Keyboard Shortcuts</h1>
<div style="text-align:center; color:#555; font-size:0.82em; margin-bottom:20px;">All actions are available without a mouse.</div>
<div style="display:flex; flex-direction:column; gap:8px; max-width:480px; margin:0 auto;">
<div style="background:#111; border:1px solid #2a2a2a; border-radius:6px; overflow:hidden;">
<div style="background:#1a1a1a; padding:6px 12px; font-size:0.72em; font-weight:bold; color:#666; text-transform:uppercase; letter-spacing:0.1em;">Actions</div>
<div style="padding:8px 12px; display:flex; flex-direction:column; gap:5px;">
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Girl card 1–9 (Approach / Interact / Infect)</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">1 – 9</span>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Any button or link with a number in its label</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">1 – 9</span>
</div>
<div style="font-size:0.78em; color:#444; margin-top:2px; line-height:1.4;">
Girl cards are numbered left to right. If no card matches, the key clicks the first visible button or link whose text contains that digit — so labelling buttons like "Continue (1)" or "Skip (2)" makes them keyboard-accessible.
</div>
</div>
</div>
<div style="background:#111; border:1px solid #2a2a2a; border-radius:6px; overflow:hidden;">
<div style="background:#1a1a1a; padding:6px 12px; font-size:0.72em; font-weight:bold; color:#666; text-transform:uppercase; letter-spacing:0.1em;">The Day</div>
<div style="padding:8px 12px; display:flex; flex-direction:column; gap:5px;">
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Advance — clicks Sleep, Wake Up, Continue or Done</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">Q</span>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Produce a parasite and end the day</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">P</span>
</div>
<div style="font-size:0.78em; color:#444; margin-top:2px; line-height:1.4;">
<b style="color:#664444;">P costs the whole day.</b> It adds one parasite and goes straight to the night report — the same as the Produce Parasite link in the side menu.
</div>
</div>
</div>
<div style="background:#111; border:1px solid #2a2a2a; border-radius:6px; overflow:hidden;">
<div style="background:#1a1a1a; padding:6px 12px; font-size:0.72em; font-weight:bold; color:#666; text-transform:uppercase; letter-spacing:0.1em;">Pages</div>
<div style="padding:8px 12px; display:flex; flex-direction:column; gap:5px;">
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Factions</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">F</span>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Goals</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">G</span>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Characters</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">C</span>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Upgrades</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">U</span>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Shortcuts (this page)</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">? / /</span>
</div>
</div>
</div>
<div style="background:#111; border:1px solid #2a2a2a; border-radius:6px; overflow:hidden;">
<div style="background:#1a1a1a; padding:6px 12px; font-size:0.72em; font-weight:bold; color:#666; text-transform:uppercase; letter-spacing:0.1em;">History</div>
<div style="padding:8px 12px; display:flex; flex-direction:column; gap:5px;">
<div style="display:flex; justify-content:space-between; font-size:0.88em;">
<span style="color:#888;">Forward / Back</span>
<span style="color:#bd59ff; font-weight:bold; font-family:monospace;">+ / -</span>
</div>
</div>
</div>
</div>/* =========================================================================
§ 6. SUSPICION SYSTEM
========================================================================= */
/* ── Core helpers ── */
window.getSuspicionTier = function() {
let s = State.variables.suspicion || 0;
if (s >= 100) return 4;
if (s >= 75) return 3;
if (s >= 50) return 2;
if (s >= 25) return 1;
return 0;
};
window.canEnterLocation = function(locName) {
let sv = State.variables;
let traits = window.LOCATION_TRAITS || {};
let trait = traits[locName] || "socialHub";
let tier = window.getSuspicionTier();
/* Police-blocked locations — cleared at DayStart */
if (sv.blockedLocations && sv.blockedLocations.indexOf(locName) !== -1) return false;
if (trait === "intimate") return true;
if (trait === "critical") return tier < 2;
return tier < 3;
};
/* `context` is optional: "party" or "activity". getUpgradeSuspicionMult() has
always handled both, but nothing ever passed one, so Discreet Gatherings
and Crowd Cover could be bought and never did anything. */
window.addSuspicion = function(amount, context) {
let sv = State.variables;
if (sv.goalBonuses) {
let b = sv.goalBonuses;
let trait = (window.LOCATION_TRAITS && sv.currentLocation)
? (window.LOCATION_TRAITS[sv.currentLocation] || "") : "";
if (b.noSuspicionAll) return;
if (b.noSuspicionSchool && trait === "academic") return;
if (b.noSuspicionIntimate && trait === "intimate") return;
}
let mult = (typeof window.getUpgradeSuspicionMult === "function")
? window.getUpgradeSuspicionMult(sv.currentLocation, context)
: 1.0;
let final = Math.round(amount * mult);
if (final <= 0) return;
sv.suspicion = Math.min(100, Math.max(0, (sv.suspicion || 0) + final));
};
window.getSuspicionColor = function() {
let s = State.variables.suspicion || 0;
if (s >= 75) return "#ff2222";
if (s >= 50) return "#ff8800";
if (s >= 25) return "#ffcc00";
return "#44ff88";
};
window.getSuspicionLabel = function() {
let s = State.variables.suspicion || 0;
if (s >= 100) return "CRITICAL";
if (s >= 75) return "DANGER";
if (s >= 50) return "HIGH";
if (s >= 25) return "ELEVATED";
return "CLEAR";
};
/* ── Player action hooks ── */
window.isAuthorityPresent = function(locationName) {
let sv = State.variables;
let roster = sv.roster;
return roster.some(id => {
let c = sv[id];
return c && c.location === locationName && c.trait === "authority" && c.corr < 50;
});
};
window.checkInfectionWitnesses = function(targetId) {
let sv = State.variables;
let location = sv.currentLocation;
let target = sv[targetId];
let ups = sv.upgrades || {};
if (target && target.trait === "authority" && !ups.infectAuthority) {
return `<span style="color:#ff4444">⚠ You cannot infect Authority figures at your current level.</span>`;
}
if (ups.highCorrNoSuspicion && target && target.corr >= 75) {
return null;
}
let witnesses = [];
sv.roster.forEach(id => {
let c = sv[id];
if (c && c.location === location && c.trait === "authority"
&& id !== targetId && c.corr < 50) {
witnesses.push(c.name);
}
});
let baseGain = 5;
if (target) {
if (target.trait === "authority") baseGain = 20;
else if (target.trait === "flashpoint") baseGain = 12;
else if (target.trait === "influential") baseGain = 8;
}
let reduction = (sv.nestSuspReduction && sv.nestSuspReduction[location]) || 0;
baseGain = Math.round(baseGain * (1 - reduction));
if (sv.goalBonuses && sv.goalBonuses.corruptedLocations
&& sv.goalBonuses.corruptedLocations.indexOf(location) !== -1) {
baseGain = Math.floor(baseGain * 0.5);
}
window.addSuspicion(baseGain);
if (witnesses.length > 0) {
let penalty = witnesses.length * 15;
window.addSuspicion(penalty);
return `<span style="color:#ff4444">⚠ WITNESSED BY AUTHORITY! (${witnesses.join(", ")}) +${penalty + baseGain} Suspicion!</span>`;
}
if (!sv.todayInfectedByLoc) sv.todayInfectedByLoc = {};
sv.todayInfectedByLoc[location] = (sv.todayInfectedByLoc[location] || 0) + 1;
if (sv.todayInfectedByLoc[location] > 1) {
window.addSuspicion(5);
return `<span style="color:#ff8844">⚠ Reckless spreading in one location. (+${baseGain + 5} Suspicion)</span>`;
}
return null;
};
window.checkRecentVectorBurst = function() {
let sv = State.variables;
if (!sv.recentVectorDays) sv.recentVectorDays = [];
sv.recentVectorDays.push(sv.day);
sv.recentVectorDays = sv.recentVectorDays.filter(d => (sv.day - d) <= 3);
if (sv.recentVectorDays.length >= 2) {
window.addSuspicion(15);
return true;
}
return false;
};
/* ── Day-end suspicion processing ── */
window.processSuspicionEvents = function(log) {
let sv = State.variables;
let roster = sv.roster;
let traits = window.LOCATION_TRAITS || {};
let ups = sv.upgrades || {};
/* Clear previous day's blocked locations */
sv.blockedLocations = [];
/* 1. Decay */
let decay = 5;
roster.forEach(id => {
let c = sv[id];
if (c && c.trait === "authority" && c.corr >= 25) decay += 3;
if (c && c.trait === "influential" && c.corr >= 50) decay += 2;
});
if (sv.suspicion > 0) sv.suspicion = Math.max(0, sv.suspicion - decay);
/* 2. Random strange behaviour */
if (!ups.noRandomSuspicion && sv.suspicion < 50) {
let infected = roster.filter(id =>
sv[id] && sv[id].infected && sv[id].corr < 100 && !sv[id].arrested
);
if (infected.length > 0 && Math.random() < (0.05 * infected.length)) {
let culprit = sv[infected[Math.floor(Math.random() * infected.length)]];
if (!(ups.highCorrNoSuspicion && culprit.corr >= 75)) {
let gain = 6;
if (culprit.trait === "authority") gain = 15;
if (culprit.trait === "flashpoint") gain = 12;
if (culprit.trait === "influential") gain = 10;
window.addSuspicion(gain);
log.push(`<span style="color:#ff8844">⚠ <b>${culprit.name}</b> acted strangely in public (+${gain} suspicion).</span>`);
}
}
}
/* 3. High-level nest heat */
Object.keys(sv.nests || {}).forEach(locName => {
let nest = sv.nests[locName];
let trait = traits[locName] || "socialHub";
if (nest.level > 3 && trait !== "intimate") {
window.addSuspicion(3);
log.push(`<span style="color:#ff8844">▲ High-level nest at <b>${locName}</b> is attracting attention (+3).</span>`);
}
});
/* 4. Tier events */
let tier = window.getSuspicionTier();
if (tier >= 1 && !sv.detectiveActive) {
sv.detectiveActive = true;
log.push(`<span style="color:#ff4444">🔍 A detective has been assigned to investigate the area.</span>`);
} else if (tier < 1 && sv.detectiveActive) {
sv.detectiveActive = false;
log.push(`<span style="color:#44ff88">✓ The detective has backed off.</span>`);
}
/* 5. Police block locations (suspicion >= 50) */
if (tier >= 2) {
/* Candidate locations: public/transient/academic — not intimate, not already blocked */
let candidates = Object.keys(traits).filter(function(locName) {
let t = traits[locName];
return t !== "intimate" && t !== "critical";
});
/* Block 1–2 locations depending on suspicion tier */
let blockCount = tier >= 3 ? 2 : 1;
let shuffled = candidates.sort(function() { return Math.random() - 0.5; });
for (let i = 0; i < Math.min(blockCount, shuffled.length); i++) {
let locName = shuffled[i];
sv.blockedLocations.push(locName);
log.push(`<span style="color:#ff8844">🚔 Police are patrolling <b>${locName}</b> — access blocked tomorrow.</span>`);
}
/* Also attempt nest raids */
Object.keys(sv.nests || {}).forEach(locName => {
let nest = sv.nests[locName];
let trait = traits[locName] || "socialHub";
if (nest.level > 0 && trait !== "intimate" && Math.random() < 0.10) {
nest.level = 0;
nest.days = 0;
nest.type = "spreading";
nest.specialisation = null;
log.push(`<span style="color:#ff4444">🔍 Police raided and destroyed the nest at <b>${locName}</b>.</span>`);
}
});
}
/* 6. Arrests (suspicion >= 75) */
if (tier >= 3) {
roster.forEach(id => {
let c = sv[id];
if (!c || !c.infected || c.arrested) return;
if (ups.noArrest) return;
if (ups.highCorrNoSuspicion && c.corr >= 75) return;
let trait = traits[c.location] || "socialHub";
if (trait !== "intimate" && Math.random() < 0.12) {
c.arrested = true;
c.location = "The Lab";
if (c.corr >= 100) {
c.labDays = 5;
log.push(`<span style="color:#ff8844">🚔 <b>${c.name}</b> was taken to <b>The Lab</b> — but there is nothing in her left to find.</span>`);
} else {
log.push(`<span style="color:#ff2222">🚔 <b>${c.name}</b> was arrested and sent to <b>The Lab</b>!</span>`);
}
}
});
}
if (sv.suspicion >= 100) {
sv.gameOver = true;
log.push(`<span style="color:#ff0000; font-size:1.3em; font-weight:bold;">☠ SUSPICION CRITICAL — YOUR COVER IS BLOWN.</span>`);
}
};
/* ── Lab decay ── */
window.processLabDecay = function(log) {
let sv = State.variables;
sv.roster.forEach(id => {
let c = sv[id];
if (!c || !c.arrested) return;
/* ── VECTORS DO NOT DECAY ──
At corr 100 she is not carrying the parasite, she IS it. There is
no infection to strip out of her and nothing for the Lab to work
against, so their tests come back clean and they have to let her
go. Five days, then out — still infected, still at 100.
labDays is only ever set here, so an ordinary girl who is later
pushed to 100 while detained picks the counter up on that night. */
if (c.corr >= 100) {
c.labDays = (c.labDays === undefined) ? 5 : c.labDays - 1;
if (c.labDays <= 0) {
c.arrested = false;
c.labDays = undefined;
c.location = "House";
log.push(`<span style="color:#bd59ff">☣ <b>${c.name}</b> was released from The Lab. They found nothing wrong with her.</span>`);
} else {
log.push(`<span style="color:#cc88ff">⚗ <b>${c.name}</b> is held at The Lab, and every test comes back clean. ${c.labDays} day${c.labDays === 1 ? "" : "s"} left.</span>`);
}
return;
}
c.corr = Math.max(0, c.corr - 10);
if (c.corr <= 0) {
c.infected = false;
c.arrested = false;
c.location = "House";
log.push(`<span style="color:#aaa">⚗ <b>${c.name}</b> was fully cleared by The Lab and released.</span>`);
} else if (c.corr < (window.getCorrCap ? window.getCorrCap(c) : 25)) {
log.push(`<span style="color:#ff8844">⚗ <b>${c.name}</b> is detained at The Lab. Corruption: ${c.corr}% (below ${window.getCorrCap ? window.getCorrCap(c) : 25})</span>`);
} else {
log.push(`<span style="color:#ff8844">⚗ <b>${c.name}</b> is detained at The Lab. Corruption: ${c.corr}%</span>`);
}
});
};/* =========================================================================
§ 7. NEST SYSTEM
========================================================================= */
/* ── Constants ── */
window.NEST_DURATIONS = { 1: 3, 2: 5, 3: 8, 4: 12, 5: 18 };
window.NEST_COSTS = { 1: 3, 2: 6, 3: 10, 4: 15 };
window.NEST_STAGES = { 0: "Clear", 1: "Seedling", 2: "Colony",
3: "Stronghold", 4: "Hive", 5: "Nexus" };
window.NEST_DETECT_BASE = { 1: 0.00, 2: 0.02, 3: 0.05, 4: 0.10, 5: 0.18 };
window.NEST_DETECT_TIER = { 0: 1.0, 1: 1.5, 2: 2.0, 3: 3.0 };
window.NEST_DECAY_BONUS = { 0: 0, 1: 0, 2: 1, 3: 2 };
/* ── Helpers ── */
window.getNestStage = function(level) {
return window.NEST_STAGES[level] || "Clear";
};
window.getNestTrait = function(location) {
return (window.LOCATION_TRAITS && window.LOCATION_TRAITS[location]) || "socialHub";
};
window.nestAllowed = function(location) {
let trait = window.getNestTrait(location);
if (trait === "critical") {
return typeof window.hasUpgrade === "function" && window.hasUpgrade("nestCritical");
}
return true;
};
/* Returns true if a nest at this location is in a safe state.
Used by nestsNeverDecay upgrade and safeHouse directive. */
window.isNestSafe = function(locName, nest) {
let sv = State.variables;
let locObj = sv.locations && sv.locations.find(function(l) { return l.name === locName; });
let pillars = locObj ? (locObj.pillars || []) : [];
if (locObj && locObj.alwaysUnsafe) return false;
if (pillars.length === 0) return true;
let trait = window.getNestTrait(locName);
let isCritical = trait === "critical";
let qualCount = pillars.filter(function(pid) {
let c = sv[pid];
if (!c) return false;
return nest.type === "breeding" ? !!c.infected : c.corr >= 25;
}).length;
if (isCritical || pillars.length === 1) {
return qualCount === pillars.length;
}
return (qualCount / pillars.length) >= 0.70;
};
window.getNestLabel = function(nest) {
if (!nest || nest.level === 0) return "None";
let stage = window.NEST_STAGES[nest.level] || "Seedling";
if (nest.type === "breeding") return stage + " [Breeding]";
if (nest.specialisation) {
let s = nest.specialisation.charAt(0).toUpperCase() + nest.specialisation.slice(1);
return stage + " [" + s + "]";
}
return stage;
};
window.getNestCount = function() {
let sv = State.variables;
return Object.keys(sv.nests || {}).filter(function(k) {
return sv.nests[k] && sv.nests[k].level > 0;
}).length;
};
/* Returns true if this nest is protected by the safeHouse directive */
window.isNestProtected = function(locName) {
let sv = State.variables;
return sv.nestProtected && (sv.nestProtected[locName] || 0) > 0;
};
/* ── Plant ── */
window.plantNest = function(location, type) {
let sv = State.variables;
let nest = sv.nests[location];
if (!nest || !window.nestAllowed(location)) return false;
if (nest.level > 0) return false;
let currentCount = window.getNestCount();
let nestCap = sv.nestCap || 2;
if (currentCount >= nestCap) return false;
let nestType = type || "spreading";
let b = sv.goalBonuses;
let isCorrupted = b && b.corruptedLocations && b.corruptedLocations.indexOf(location) !== -1;
let cost = nestType === "breeding" ? 1 : (isCorrupted ? 1 : 2);
if (sv.parasite < cost) return false;
let baseDays = window.NEST_DURATIONS[1];
let ups = sv.upgrades || {};
if (ups.nestDuration1) baseDays = Math.round(baseDays * 1.5);
if (ups.nestDuration2) baseDays = Math.round(baseDays * 1.5);
sv.parasite -= cost;
nest.level = 1;
nest.days = baseDays;
nest.type = nestType;
nest.specialisation = null;
return true;
};
/* ── Upgrade (spreading nests only) ── */
window.upgradeNest = function(location) {
let sv = State.variables;
let nest = sv.nests[location];
if (!nest) return false;
if (nest.type === "breeding") return false;
if (nest.level === 0 || nest.level >= 5) return false;
if (nest.level === 2) return false;
let cost = window.NEST_COSTS[nest.level];
if (!cost || sv.parasite < cost) return false;
sv.parasite -= cost;
nest.level++;
let baseDays = window.NEST_DURATIONS[nest.level];
let ups = sv.upgrades || {};
if (ups.nestDuration1) baseDays = Math.round(baseDays * 1.5);
if (ups.nestDuration2) baseDays = Math.round(baseDays * 1.5);
nest.days = baseDays;
if (nest.level > 3 && window.getNestTrait(location) !== "intimate" && nest.specialisation !== "stealth") {
window.addSuspicion(10);
}
return true;
};
/* ── Specialise (L2 → L3) ── */
window.specialiseNest = function(location, specialisation) {
let sv = State.variables;
let nest = sv.nests[location];
if (!nest) return false;
if (nest.type !== "spreading") return false;
if (nest.level !== 2) return false;
if (!["corruption", "spread", "stealth"].includes(specialisation)) return false;
let cost = window.NEST_COSTS[2];
if (sv.parasite < cost) return false;
sv.parasite -= cost;
nest.level = 3;
nest.specialisation = specialisation;
let baseDays = window.NEST_DURATIONS[3];
let ups = sv.upgrades || {};
if (ups.nestDuration1) baseDays = Math.round(baseDays * 1.5);
if (ups.nestDuration2) baseDays = Math.round(baseDays * 1.5);
nest.days = baseDays;
if (specialisation !== "stealth" && window.getNestTrait(location) !== "intimate") {
window.addSuspicion(5);
}
return true;
};
/* ── Upgrade via vector ── */
window.upgradeNestWithVector = function(location, charId) {
let nest = State.variables.nests[location];
let charObj = State.variables[charId];
if (!nest || !charObj) return false;
if (nest.type === "breeding") return false;
if (nest.level === 0 || nest.level >= 5) return false;
if (nest.level === 2) return false;
if (!charObj.breed) return false;
if (charObj.location !== location) return false;
charObj.breed = false;
nest.level++;
nest.days += window.NEST_DURATIONS[nest.level];
return true;
};
/* ── BREEDING NEST daily effect ── */
window.applyBreedingEffect = function(locName, nest, log) {
let sv = State.variables;
let ups = sv.upgrades || {};
let gain = ups.nestBreedingBoost ? 2 : 1;
sv.parasite = (sv.parasite || 0) + gain;
};
/* ── SPREADING NEST location-typed effect (L3+) ── */
window.applyNestEffect = function(locName, nest, charsHere, log) {
let sv = State.variables;
let level = nest.level;
let trait = window.getNestTrait(locName);
let spec = nest.specialisation;
let capOf = function(ch) { return (typeof window.getCorrCap === "function") ? window.getCorrCap(ch) : 25; };
let roster = sv.roster;
if (level < 3) return;
/* ── STEALTH ── */
if (spec === "stealth") {
charsHere.forEach(id => {
let c = sv[id];
if (c && c.infected && c.corr < capOf(c)) {
c.corr = Math.min(capOf(c), c.corr + 1);
}
});
if (!sv.nestSuspReduction) sv.nestSuspReduction = {};
sv.nestSuspReduction[locName] = level >= 5 ? 1.0 : level >= 4 ? 0.75 : 0.50;
return;
}
/* ── CORRUPTION specialisation ── */
if (spec === "corruption") {
let bonus = level >= 5 ? 5 : level >= 4 ? 4 : 3;
charsHere.forEach(id => {
let c = sv[id];
if (!c || !c.infected || c.corr >= capOf(c)) return;
c.corr = Math.min(capOf(c), c.corr + bonus);
});
roster.forEach(id => {
let c = sv[id];
if (!c || !c.infected || c.arrested || c.corr >= capOf(c)) return;
if (charsHere.indexOf(id) !== -1) return;
let anchor = c.schedule && c.schedule.anchor
? (sv.isWeekend ? c.schedule.anchor.weekend : c.schedule.anchor.weekday)
: null;
if (anchor === locName) {
c.corr = Math.min(capOf(c), c.corr + Math.ceil(bonus / 2));
}
});
return;
}
/* ── SPREAD specialisation ── */
if (spec === "spread") {
let chance = level >= 5 ? 0.50 : level >= 4 ? 0.40 : 0.30;
charsHere.forEach(id => {
let c = sv[id];
if (!c || c.arrested || c.infected) return;
/* An ESTABLISHED nest keeps working, but taking a NEW girl is
automatic infection, so autoInfect gates it. The +1 to girls
already infected, below, is not gated. */
if (!window.canInfect(c) || !window.autoInfectOn()) return;
if (Math.random() < chance) {
window.recordInfection(c, "nest", locName);
c.corr = Math.min(capOf(c), c.corr + 2);
let lbl = c.met ? `<b>${c.name}</b>` : `<b>someone</b>`;
log.push(`<span style="color:#bd59ff">Nest at <b>${locName}</b> spread to ${lbl}.</span>`);
}
});
charsHere.forEach(id => {
let c = sv[id];
if (c && c.infected && c.corr < capOf(c)) {
c.corr = Math.min(capOf(c), c.corr + 1);
}
});
return;
}
/* ── UNSPECIALISED L3+ effects by trait ──
"critical" has no case of its own and the switch has no default, so a
nest in the Police Station, Courthouse, Town Hall or The Lab produced
NOTHING at L3+ unless it was specialised — despite costing an upgrade
to plant and the Tutorial promising it "falls back to social hub
behaviour". Map it to socialHub so the promise holds. */
if (trait === "critical") trait = "socialHub";
switch (trait) {
case "intimate": {
charsHere.forEach(id => {
let c = sv[id];
if (c && c.infected && c.corr < capOf(c)) {
let bonus = level >= 5 ? 3 : level >= 4 ? 2 : 1;
c.corr = Math.min(capOf(c), c.corr + bonus);
}
});
if (!sv.nestSuspReduction) sv.nestSuspReduction = {};
sv.nestSuspReduction[locName] = level >= 5 ? 0.60 : level >= 4 ? 0.40 : 0.20;
break;
}
case "academic": {
let bonus = level >= 5 ? 3 : level >= 4 ? 2 : 1;
roster.forEach(id => {
let c = sv[id];
if (!c || !c.infected || c.arrested || c.corr >= capOf(c)) return;
let anchor = c.schedule && c.schedule.anchor
? (sv.isWeekend ? c.schedule.anchor.weekend : c.schedule.anchor.weekday)
: null;
if (anchor === locName) {
c.corr = Math.min(capOf(c), c.corr + bonus);
let lbl = c.met ? `<b>${c.name}</b>` : `<b>someone</b>`;
log.push(`Nest at <b>${locName}</b> deepened hold on ${lbl} (+${bonus}).`);
}
});
if (level >= 5) {
charsHere.forEach(id => {
let c = sv[id];
if (!window.canInfect(c) || !window.autoInfectOn()) return;
if (c && !c.infected && c.corr < 25 && Math.random() < 0.20) {
window.recordInfection(c, "nest", locName);
c.corr = Math.min(Math.min(25, capOf(c)), c.corr + 2);
let lbl = c.met ? `<b>${c.name}</b>` : `<b>someone</b>`;
log.push(`<span style="color:#bd59ff">Nexus at <b>${locName}</b> ensnared ${lbl}.</span>`);
}
});
}
break;
}
case "socialHub": {
let chance = level >= 5 ? 0.40 : level >= 4 ? 0.30 : 0.20;
let gain = level >= 5 ? 3 : level >= 4 ? 2 : 1;
charsHere.forEach(id => {
let c = sv[id];
if (!c || c.arrested) return;
if (!c.infected && window.canInfect(c) && window.autoInfectOn()
&& Math.random() < chance) {
window.recordInfection(c, "nest", locName);
c.corr = Math.min(Math.min(25, capOf(c)), c.corr + gain);
let lbl = c.met ? `<b>${c.name}</b>` : `<b>someone</b>`;
log.push(`Nest at <b>${locName}</b> seeped into ${lbl} (+${gain}).`);
} else if (c.infected && c.corr < capOf(c)) {
c.corr = Math.min(capOf(c), c.corr + gain);
}
});
break;
}
case "outdoor": {
if (!sv.nestDriftBoost) sv.nestDriftBoost = {};
sv.nestDriftBoost[locName] = level >= 5 ? 3.0 : level >= 4 ? 2.0 : 1.5;
charsHere.forEach(id => {
let c = sv[id];
if (c && c.infected && c.corr < capOf(c)) c.corr = Math.min(capOf(c), c.corr + 1);
});
break;
}
case "transient": {
let chance = level >= 5 ? 0.35 : level >= 4 ? 0.25 : 0.15;
charsHere.forEach(id => {
let c = sv[id];
if (!c || c.infected || c.arrested) return;
if (!window.canInfect(c) || !window.autoInfectOn()) return;
if (Math.random() < chance) {
/* This used to raise corruption first and only infect at
level 5 once she happened to reach corr 5 — so a level
3-4 transient nest quietly ticked uninfected girls up
forever, and a level 5 one built up 5 points on a clean
girl before the infection was recorded. A girl the nest
has taken hold of IS infected; record it up front. */
window.recordInfection(c, "nest", locName);
c.corr = Math.min(Math.min(25, capOf(c)), c.corr + 1);
if (c.corr === 0) c.corr = 1;
let lbl = c.met ? `<b>${c.name}</b>` : `<b>someone</b>`;
if (level >= 5) {
log.push(`<span style="color:#bd59ff">Nexus at <b>${locName}</b> dragged ${lbl} under.</span>`);
} else {
log.push(`Nest at <b>${locName}</b> seeded ${lbl}.`);
}
}
});
break;
}
}
};
/* ── Detection check ── */
window.checkNestDetection = function(locName, nest, log) {
/* Safe House directive protection — no detection at all */
if (window.isNestProtected(locName)) return false;
let trait = window.getNestTrait(locName);
let spec = nest.specialisation;
/* Stealth L5: completely undetectable */
if (spec === "stealth" && nest.level >= 5) return false;
/* Intimate nests never detected */
if (trait === "intimate") return false;
/* locControlCritical upgrade */
if (trait === "critical") {
let sv = State.variables;
let ups = sv.upgrades || {};
let dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
if (ups.locControlCritical && dominated.indexOf(locName) !== -1) return false;
}
let tier = window.getSuspicionTier();
let base = window.NEST_DETECT_BASE[nest.level] || 0;
let mult = window.NEST_DETECT_TIER[tier] || 1.0;
if (spec === "stealth") base = base * 0.25;
/* locControlOutdoor */
if (trait === "outdoor" || trait === "transient") {
let sv = State.variables;
let ups = sv.upgrades || {};
let dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
if (ups.locControlOutdoor && dominated.indexOf(locName) !== -1) base *= 0.5;
}
/* nestDecayOutdoor upgrade also halves detection for outdoor/transient */
if (trait === "outdoor" || trait === "transient") {
let ups = (State.variables.upgrades || {});
if (ups.nestDecayOutdoor) base *= 0.5;
}
let chance = base * mult;
if (Math.random() >= chance) return false;
let suspGain = 10 + (nest.level * 5);
if (spec === "stealth") suspGain = Math.floor(suspGain * 0.5);
window.addSuspicion(suspGain);
nest.level = Math.max(0, nest.level - 1);
if (nest.level === 0) {
nest.days = 0;
nest.type = "spreading";
nest.specialisation = null;
log.push(`<span style="color:#ff4444">⚠ Nest at <b>${locName}</b> was discovered and destroyed! (+${suspGain} suspicion)</span>`);
} else {
nest.days = Math.max(1, nest.days - 2);
log.push(`<span style="color:#ff8844">⚠ Nest at <b>${locName}</b> partially detected. Downgraded to ${window.NEST_STAGES[nest.level]}. (+${suspGain} suspicion)</span>`);
}
return true;
};
/* ── Police nest destruction ── */
window.checkPoliceDestroyNests = function(log) {
let sv = State.variables;
let tier = window.getSuspicionTier();
let ups = sv.upgrades || {};
[
{ id: "angel", baseChance: 0.25, tierMult: 0.15, intimateAtTier: 3 },
{ id: "ember", baseChance: 0.15, tierMult: 0.10, intimateAtTier: 99 }
].forEach(function(cfg) {
let girl = sv[cfg.id];
if (!girl || !girl.location) return;
let nest = sv.nests[girl.location];
let trait = window.getNestTrait(girl.location);
let canSearch = trait !== "intimate" || tier >= cfg.intimateAtTier;
if (!nest || nest.level === 0 || !canSearch) return;
/* Safe House directive protection */
if (window.isNestProtected(girl.location)) return;
let spec = nest.specialisation;
if (spec === "stealth" && nest.level >= 5) return;
let dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
if (ups.locControlIntimate && trait === "intimate" && dominated.indexOf(girl.location) !== -1) return;
let chance = cfg.baseChance + (tier * cfg.tierMult);
if (spec === "stealth") chance = chance * 0.3;
if (Math.random() >= chance) return;
let label = cfg.id === "angel" ? "Angel" : "Ember";
let susp = cfg.id === "angel" ? 5 : 3;
window.addSuspicion(susp);
nest.level = Math.max(0, nest.level - 1);
if (nest.level === 0) {
nest.days = 0;
nest.type = "spreading";
nest.specialisation = null;
log.push(`<span style="color:#ff2222">🔍 ${label} found and destroyed the nest at <b>${girl.location}</b>! (+${susp} suspicion)</span>`);
} else {
log.push(`<span style="color:#ff8844">🔍 ${label} damaged the nest at <b>${girl.location}</b>. Now: ${window.NEST_STAGES[nest.level]}. (+${susp} suspicion)</span>`);
}
});
};/* =========================================================================
§ 8. ROAMING SYSTEM
========================================================================= */
/* ── processDayEnd ── */
window.processDayEnd = function() {
let log = [];
let sv = State.variables;
let roster = sv.roster;
// STEP 1: Passive tick (respects per-girl corruption cap and upgrade bonuses)
roster.forEach(id => {
let c = sv[id];
if (!c || !c.infected || c.arrested) return;
/* Captives are excluded here. processCaptives() at STEP 5b already
gives them infectionPower + parasiteLevel, ignoring their cap — so
without this they collected BOTH ticks on the same night, plus the
dominated-location bonus below. At infection power 7 that was
1 + 7 + 9 = 17 on the first night, and more with corr-tick
upgrades. Being held is its own progression; it should not stack
with the ordinary one. */
if (c.captive) return;
let cap = window.getCorrCap ? window.getCorrCap(c) : 25;
if (c.corr >= cap) return;
let oldSuffix = window.getCorrSuffix(c.corr);
let bonus = window.getUpgradeCorrBonus ? window.getUpgradeCorrBonus(id, c.location) : 0;
let tick = (sv.infectionPower || 1) + bonus;
c.corr = Math.min(cap, c.corr + tick);
let newSuffix = window.getCorrSuffix(c.corr);
if (newSuffix !== oldSuffix)
log.push(`<b>${c.name}</b> has reached a new stage: ${newSuffix}.`);
});
// Corrupted location passive bonus
/* This had no .infected check, so ANY girl standing at a dominated
location gained +1 corruption every single night whether or not she
carried the parasite. That was the silent creep on clean girls: a
location you dominated early would slowly corrupt every uninfected
woman whose schedule passed through it. Corruption without infection
is not a thing the game models anywhere else. */
let _b = sv.goalBonuses;
let _cl = _b ? (_b.corruptedLocations || []) : [];
if (_cl.length > 0) {
roster.forEach(id => {
let c = sv[id];
if (!c || !c.infected || c.arrested || !c.location) return;
if (c.captive) return; /* see STEP 1 — no double tick */
let cap = window.getCorrCap ? window.getCorrCap(c) : 25;
if (c.corr >= cap) return;
if (_cl.indexOf(c.location) !== -1)
c.corr = Math.min(cap, c.corr + 1);
});
}
// STEP 1b: Upgrade-driven passive effects
if (typeof window.processUpgradeEffects === "function") {
window.processUpgradeEffects(log);
}
// STEP 2: Vector spread (requires Vector Protocol upgrade)
let vectorsUnlocked = sv.upgrades && sv.upgrades.vectors;
if (vectorsUnlocked) {
roster.forEach(id => {
let vector = sv[id];
if (!vector || vector.corr < 100 || vector.arrested) return;
if (vector.vectorTarget) {
let target = sv[vector.vectorTarget];
if (target && target.corr < 100 && !target.arrested
&& (target.infected ? true : window.canInfect(target))) {
target.corr = Math.min(100, target.corr + 10);
/* The player pointed the vector at her, but the infection
still happens overnight without a click. Blocked when
autoInfect is off; the +10 on an already-infected girl
is not. */
if (!target.infected && window.autoInfectOn()) window.recordInfection(target, "vector", target.location);
log.push(`<b>${vector.name}</b> focused on <b>${target.name}</b> (+10).`);
if (target.corr >= 100 && window.checkRecentVectorBurst())
log.push(`<span style="color:#ff8844">⚠ Multiple Vectors created rapidly (+15 suspicion).</span>`);
}
vector.vectorTarget = null;
} else if (vector.connections && vector.connections.length > 0) {
let valid = vector.connections.filter(cid => {
let t = sv[cid];
return t && t.corr < 100 && !t.arrested
&& (t.infected ? true : window.canInfect(t));
});
if (valid.length > 0) {
let target = sv[valid[Math.floor(Math.random() * valid.length)]];
if (Math.random() < 0.30) {
/* A vector seeds the parasite into ONE girl in her
lifetime. Without this every vector infects a new
girl every night and the roster is gone in a week.
She can still deepen an existing infection forever. */
/* Automatic: a vector taking a girl the player never
chose. Blocked when autoInfect is off. Deepening an
ALREADY infected girl, below, is not blocked. */
if (!target.infected && !vector.vectorSpent && window.autoInfectOn()) {
window.recordInfection(target, "vector", target.location);
vector.vectorSpent = true;
if (target.corr === 0) target.corr = 1;
log.push(`<span style="color:#bd59ff"><b>${vector.name}</b></span> (Vector) secretly infected <b>${target.name}</b>. <span style="color:#666;">She has no seed left to give.</span>`);
} else if (target.infected && target.corr < 100) {
target.corr = Math.min(100, target.corr + 3);
log.push(`<b>${vector.name}</b> influenced <b>${target.name}</b> (+3).`);
}
if (target.corr >= 100 && window.checkRecentVectorBurst())
log.push(`<span style="color:#ff8844">⚠ Multiple Vectors created rapidly (+15 suspicion).</span>`);
}
}
}
});
}
// STEP 3: Nest effects + detection + decay
let suspTier = window.getSuspicionTier();
let decayBonus = window.NEST_DECAY_BONUS[suspTier] || 0;
let nestsNeverDecay = sv.upgrades && sv.upgrades.nestsNeverDecay;
sv.nestSuspReduction = {};
sv.nestDriftBoost = {};
/* "Rooted Network" (nestDecayOutdoor) says: "Nests in outdoor and
transient locations decay at half the normal rate." It was only ever
applied to DETECTION in checkNestDetection, so the decay half of its
own description did nothing. Halve the decay here. */
var rootedNetwork = sv.upgrades && sv.upgrades.nestDecayOutdoor;
function decayFor(locName) {
var d = 1 + decayBonus;
if (rootedNetwork) {
var t = window.getNestTrait ? window.getNestTrait(locName) : null;
if (t === "outdoor" || t === "transient") d = d / 2;
}
return d;
}
Object.keys(sv.nests).forEach(locName => {
let nest = sv.nests[locName];
if (nest.level === 0) return;
let nestIsSafe = false;
if (nestsNeverDecay && typeof window.isNestSafe === "function") {
nestIsSafe = window.isNestSafe(locName, nest);
}
if (nest.type === "breeding") {
let breedGain = (sv.upgrades && sv.upgrades.nestBreedingBoost) ? 2 : 1;
window.applyBreedingEffect(locName, nest, log, breedGain);
window.checkNestDetection(locName, nest, log);
if (nest.level > 0) {
if (!nestIsSafe) {
nest.days = Math.max(0, nest.days - decayFor(locName));
}
if (nest.days <= 0) {
nest.level = 0;
nest.type = "spreading";
nest.specialisation = null;
log.push(`The breeding nest at <b>${locName}</b> has withered.`);
}
}
return;
}
let charsHere = roster.filter(id =>
sv[id] && sv[id].location === locName && !sv[id].arrested
);
if (nest.specialisation !== "stealth" && charsHere.length > 0) {
let target = sv[charsHere[Math.floor(Math.random() * charsHere.length)]];
let cap = window.getCorrCap ? window.getCorrCap(target) : 25;
/* An uninfected girl is only touched here if the nest can actually
take her — canInfect() covers the hivemind ceiling and the
unmet rule. She is infected in the same breath, below, so this
never leaves a clean girl carrying corruption. */
if (target && target.corr < cap
&& (target.infected ? true : (window.canInfect(target) && window.autoInfectOn()))) {
let gain = nest.level * 2;
target.corr = Math.min(cap, target.corr + gain);
if (!target.infected && target.corr > 0) {
window.recordInfection(target, "nest", locName);
let tLabel = target.met ? `<b>${target.name}</b>` : `<b>someone</b>`;
log.push(`Nest at <b>${locName}</b> ensnared ${tLabel}.`);
if (window.isAuthorityPresent(locName)) {
window.addSuspicion(15);
log.push(`<span style="color:#ff4444">⚠ Nest infection at ${locName} witnessed! (+15 suspicion)</span>`);
}
}
}
}
window.applyNestEffect(locName, nest, charsHere, log);
window.checkNestDetection(locName, nest, log);
if (nest.level > 0) {
if (!nestIsSafe) {
nest.days = Math.max(0, nest.days - decayFor(locName));
}
if (nest.days <= 0) {
nest.level = 0;
nest.type = "spreading";
nest.specialisation = null;
log.push(`The nest at <b>${locName}</b> has collapsed.`);
}
}
});
window.checkPoliceDestroyNests(log);
// STEP 4: Bred vector resolution
roster.forEach(id => {
let c = sv[id];
if (!c || !c.breed || c.arrested) return;
if (Math.random() < 0.90) {
sv.parasite++;
} else {
let loc = c.location;
/* A bred girl spawning a nest is a NEW spreading nest appearing
with no player action, so autoInfect gates it -- that is the
half of this setting about nests. An established nest the
player planted is untouched and keeps working; only the
automatic creation of a new one stops. She yields a parasite
instead, exactly as she does when the location already has a
nest. */
if (loc && sv.nests[loc] && sv.nests[loc].level === 0 && window.autoInfectOn()) {
sv.nests[loc].level = 1;
sv.nests[loc].days = window.NEST_DURATIONS[1];
log.push(`<b>${c.name}</b> spawned a Nest at <b>${loc}</b>!`);
} else {
sv.parasite++;
}
}
c.breed = false;
});
// STEP 5: Faction events
window.processFactions(log);
// STEP 5b: Captive corruption tick
window.processCaptives(log);
// STEP 5c: Sync faction member connections
window.syncFactionConnections();
// STEP 6: Suspicion processing
window.processSuspicionEvents(log);
// STEP 7: Lab decay
window.processLabDecay(log);
// STEP 8: Advance day
sv.day++;
if (sv.daysOfWeek) sv.weekDay = sv.daysOfWeek[sv.day % 7];
// STEP 9: Goal completion check
window.checkGoalCompletion(log);
/* STEP 9b: Roll new goals, and say so.
This used to happen in two places that both got it wrong. The call at
the end of processFactions ran at STEP 5, BEFORE sv.day++ below, so its
cooldown test (day - lastGoalDay < 5) was always measured against
yesterday and it returned early every single night — the log it was
handed never received anything. The roll that actually fired was the one
in DayStart the next morning, which passes no log, so new goals appeared
on the Goals screen with nothing said about them.
Rolling here instead: after the day has advanced, after completions have
freed their slots, and with the night report's log in hand. */
window.rollNewGoals(false, null, log);
// STEP 10: Corrupted locations from faction leaders
window.checkCorruptedLocations(log);
State.temporary.dayLog = log;
};
/* ── assignDailyLocations ── */
window.assignDailyLocations = function() {
var sv = State.variables;
var dayIndex = sv.day % 7;
var isWE = (dayIndex === 0 || dayIndex === 6);
sv.isWeekend = isWE;
var rosterIds = sv.roster;
var maxPerLoc = 7;
var locPopulation = {};
sv.girlLocations = {};
var policeVars = ["angel", "jane", "ember"];
var outChance = {
"busy": 0.25,
"homebody": 0.05,
"routine-bound": isWE ? 0.15 : 0.05,
"weekendSocial": isWE ? 0.10 : 0.05,
"social": 0.10,
"restless": 0.10
};
function getWeights(trait) {
var t = trait === "weekendSocial" ? (isWE ? "social" : "homebody") : trait;
switch (t) {
case "homebody": return { a: 0.70, s: 0.20, w: 0.10 };
case "routine-bound": return isWE ? { a: 0.35, s: 0.35, w: 0.30 }
: { a: 0.65, s: 0.25, w: 0.10 };
case "restless": return { a: 0.35, s: 0.30, w: 0.35 };
case "social": return { a: 0.45, s: 0.25, w: 0.30 };
default: return { a: 0.50, s: 0.30, w: 0.20 };
}
}
function locObj(name) {
return sv.locations.find(function(l) { return l.name === name; });
}
/* Only family, core support, or a girl at 75+ will go to the mansion.
Captives are the exception: they go nowhere else, but the mansion is
where you keep them, so they are always allowed there. */
function haremEligible(girl) {
if (!girl) return false;
if (girl.captive) return true;
if (girl.corr >= 75) return true;
return window.groupHasHaremPull(girl.group);
}
function locAvailableForRoaming(name, forSchoolChar, girl) {
var l = locObj(name);
if (!l) return false;
if (!l.unlocked) return false;
if (l.harem && !haremEligible(girl)) return false;
var dayOk = isWE ? !!l.weekends : !!l.weekdays;
if (dayOk) return true;
if (forSchoolChar && l.section && SCHOOL_SECTIONS.indexOf(l.section) !== -1) {
return isWE ? !!l.weekends : true;
}
return false;
}
function locAvailable(name) {
var l = locObj(name);
if (!l || !l.unlocked) return false;
return isWE ? !!l.weekends : !!l.weekdays;
}
function hasRoom(name) {
return (locPopulation[name] || 0) < maxPerLoc;
}
function isSocial(girl) {
var t = girl.roamTrait;
return t === "social" || (t === "weekendSocial" && isWE);
}
function placeGirl(girl, name) {
girl.location = name;
sv.girlLocations[girl.var] = name;
locPopulation[name] = (locPopulation[name] || 0) + 1;
}
var SCHOOL_SECTIONS = ["School", "Dorms"];
/* Was a hardcoded list of five group NAMES — a fourth copy of the group
data. The `school` flag in GROUP_DEFS carries it now, so a mod group
can opt in without touching this file. */
/* Non-students who happen to sit in a school-flagged group.
They keep their scheduled locations but must never be pulled into
School/Dorms locations by the wildcard roamer. */
/* Adults in school-flagged groups who are NOT students. They keep every
location in their own schedule, but the wildcard roamer must never
drop them into a School/Dorms location they didn't ask for.
(Anya is school staff and Alina is already Town Folks, so neither
needs listing — Alina isn't in a SCHOOL_GROUP at all.) */
/* The hand-written NON_STUDENTS list that used to live here has gone.
Who belongs on campus is now read from the data: the group's `school`
flag, plus `student: false` on the record of an adult who is in a
school group socially rather than as a pupil. See GroupData. */
var wcPool = sv.locations
.filter(function(l) {
if (l.harem) return false; /* drawn by its own 10% roll */
if (!l.unlocked) return false;
if (isWE ? !l.weekends : !l.weekdays) return false;
return ["outdoor", "socialHub", "transient"].indexOf(l.trait) !== -1;
})
.map(function(l) { return l.name; });
/* The mansion, if it exists and is open. */
var haremLoc = sv.locations.find(function(l) { return l.harem && l.unlocked; });
var HAREM_PULL = 0.10;
function pickRandom(pool) {
return pool.length ? pool[Math.floor(Math.random() * pool.length)] : null;
}
function pickSocial(pool) {
if (!pool.length) return null;
var total = pool.reduce(function(s, l) { return s + 1 + (locPopulation[l] || 0); }, 0);
var roll = Math.random() * total, cum = 0;
for (var i = 0; i < pool.length; i++) {
cum += 1 + (locPopulation[pool[i]] || 0);
if (roll <= cum) return pool[i];
}
return pool[pool.length - 1];
}
function applyPairing(girl, pool) {
if (!girl.pairing || girl.pairing === "none" || girl.pairing === "low") return pool;
if (!girl.connections || !girl.connections.length) return pool;
var boost = girl.pairing === "high" ? 4 : 2;
var connLocs = {};
girl.connections.forEach(function(cv) {
var placed = sv.girlLocations[cv];
if (placed && pool.indexOf(placed) !== -1)
connLocs[placed] = (connLocs[placed] || 0) + 1;
});
if (!Object.keys(connLocs).length) return pool;
var weighted = [];
pool.forEach(function(loc) {
var copies = connLocs[loc] ? Math.ceil(boost * connLocs[loc]) : 1;
for (var i = 0; i < copies; i++) weighted.push(loc);
});
return weighted;
}
function handleOverflow(girl, blocked, sched, schoolOk) {
/* schoolOk may be a boolean (legacy) or a per-location predicate */
var allow = (typeof schoolOk === "function")
? schoolOk
: function() { return !!schoolOk; };
if (Math.random() < 0.5) {
var opts = sched.filter(function(l) {
return l !== blocked && locAvailableForRoaming(l, allow(l), girl) && hasRoom(l);
});
if (!opts.length) {
opts = wcPool.filter(function(l) {
if (l === blocked || !hasRoom(l)) return false;
var lo = locObj(l);
if (lo && SCHOOL_SECTIONS.indexOf(lo.section) !== -1 && !allow(l)) return false;
return true;
});
}
if (opts.length) { placeGirl(girl, opts[0]); return; }
}
girl.location = null;
sv.girlLocations[girl.var] = null;
}
var civilianIds = rosterIds.filter(function(id) { return policeVars.indexOf(id) === -1; });
var ordered = civilianIds.slice().sort(function(a, b) {
var ga = sv[a], gb = sv[b];
if (!ga || !gb) return 0;
var sa = isSocial(ga) ? 1 : 0, sb = isSocial(gb) ? 1 : 0;
return sa !== sb ? sa - sb : Math.random() - 0.5;
});
ordered.forEach(function(charId) {
var girl = sv[charId];
if (!girl || !girl.schedule) return;
/* ── CAPTIVES DO NOT ROAM ──
She is being held. The only place she can be is the mansion, and
only once it exists. Otherwise she is off the map entirely. */
if (girl.captive) {
if (haremLoc && hasRoom(haremLoc.name)) {
placeGirl(girl, haremLoc.name);
} else {
girl.location = null;
sv.girlLocations[charId] = null;
}
return;
}
/* ── FACTION DIRECTIVES THAT MOVE PEOPLE ──
Shadow and Concentrate both set c.location during DayEnd, and then
this function overwrote it a moment later at DayStart, so neither
directive ever did anything visible. Honour them here instead,
where placement actually happens.
Shadow — everyone to their own anchor (predictable)
Concentrate — everyone to the faction's home location */
var _dirFaction = (sv.factions || []).find(function(f) {
return f.directive && f.members.indexOf(charId) !== -1;
});
if (_dirFaction) {
var _did = _dirFaction.directive.id;
if (_did === "concentrate" && _dirFaction.homeLocation
&& hasRoom(_dirFaction.homeLocation)) {
placeGirl(girl, _dirFaction.homeLocation);
return;
}
if (_did === "shadow" && girl.schedule.anchor) {
var _anc = isWE ? girl.schedule.anchor.weekend : girl.schedule.anchor.weekday;
if (_anc && hasRoom(_anc)) { placeGirl(girl, _anc); return; }
}
}
var sched = isWE ? girl.schedule.weekend : girl.schedule.weekday;
if (!sched || !sched.length) return;
var anchorField = girl.schedule.anchor;
var anchor = anchorField ? (isWE ? anchorField.weekend : anchorField.weekday) : sched[0];
var secondary = sched.filter(function(l) { return l !== anchor; });
var oc = outChance[girl.roamTrait] !== undefined ? outChance[girl.roamTrait] : 0.10;
if (Math.random() < oc) {
girl.location = null;
sv.girlLocations[charId] = null;
return;
}
/* Students, plus school staff — anyone whose group is flagged
`school` and who isn't an adult marked `student: false`.
Staff are included here deliberately: a professor turning up
anywhere on campus is correct, and this only governs the
School/Dorms WILDCARD pool. isStudent() is the narrower
predicate and excludes them, which is right for detention. */
var isSchoolChar = window.groupIsSchool(girl.group)
&& girl.student !== false;
/* Safety net: a girl who is NOT flagged as a student may still have
School/Dorms stops in her own schedule (Melissa reads at the
Library, Anya works the Staff Room). Those remain reachable via
the anchor/secondary paths below — but she is still excluded
from the School/Dorms wildcard pool, which is what was dropping
non-students into Dormitory Hall. */
var ownSchoolStops = sched.filter(function(l) {
var lo = locObj(l);
return lo && SCHOOL_SECTIONS.indexOf(lo.section) !== -1;
});
function allowedSchoolLoc(name) {
return isSchoolChar || ownSchoolStops.indexOf(name) !== -1;
}
/* ── The mansion pulls its own crowd ──
Once unlocked, an eligible girl has a flat 10% chance of simply
being there instead of following her schedule. */
if (haremLoc && haremEligible(girl) && hasRoom(haremLoc.name)
&& Math.random() < HAREM_PULL) {
placeGirl(girl, haremLoc.name);
return;
}
var w = getWeights(girl.roamTrait);
var anchorOk = locAvailableForRoaming(anchor, allowedSchoolLoc(anchor), girl) && hasRoom(anchor);
if (!anchorOk) { w.s += w.a * 0.60; w.w += w.a * 0.40; w.a = 0; }
var roll = Math.random();
var chosen = null;
var social = isSocial(girl);
if (w.a > 0 && roll < w.a) {
chosen = anchor;
} else if (roll < w.a + w.s) {
var availSec = secondary.filter(function(l) {
if (!locAvailableForRoaming(l, allowedSchoolLoc(l), girl) || !hasRoom(l)) return false;
var lo = locObj(l);
if (lo && SCHOOL_SECTIONS.indexOf(lo.section) !== -1 && !allowedSchoolLoc(l)) return false;
return true;
});
if (availSec.length) {
var pool = applyPairing(girl, availSec);
chosen = social ? pickSocial(pool) : pickRandom(pool);
}
}
if (!chosen) {
var availWC = wcPool.filter(function(l) {
if (!hasRoom(l)) return false;
var lo = locObj(l);
if (lo && SCHOOL_SECTIONS.indexOf(lo.section) !== -1 && !allowedSchoolLoc(l)) return false;
return true;
});
if (availWC.length) {
var wcPaired = applyPairing(girl, availWC);
chosen = social ? pickSocial(wcPaired) : pickRandom(wcPaired);
}
}
if (!chosen && locAvailableForRoaming(anchor, allowedSchoolLoc(anchor), girl)) chosen = anchor;
if (!chosen) { girl.location = null; sv.girlLocations[charId] = null; return; }
if (!hasRoom(chosen)) { handleOverflow(girl, chosen, sched, allowedSchoolLoc); return; }
placeGirl(girl, chosen);
});
/* Infected drift.
An outdoor nest at level 3+ writes sv.nestDriftBoost[loc] (1.5 / 2.0 /
3.0) and the location card promises "Infected are drawn to this place".
Nothing read that value — the destination was picked uniformly at
random, so the promise was never kept and outdoor was the weakest
specialisation by a wide margin. The boost is now a weight on the
draw: a 3.0 location is three times as likely as an unboosted one. */
ordered.forEach(function(charId) {
var girl = sv[charId];
if (!girl || !girl.infected || !girl.location) return;
if (girl.captive) return; /* held — she drifts nowhere */
if (Math.random() >= 0.10) return;
var open = sv.locations.filter(function(l) {
if (!l.unlocked) return false;
if (l.harem && !haremEligible(girl)) return false;
return (isWE ? l.weekends : l.weekdays) && hasRoom(l.name);
});
if (!open.length) return;
var boosts = sv.nestDriftBoost || {};
var total = 0;
open.forEach(function(l) { total += (boosts[l.name] || 1); });
var roll = Math.random() * total;
var dest = open[open.length - 1].name;
for (var di = 0; di < open.length; di++) {
roll -= (boosts[open[di].name] || 1);
if (roll <= 0) { dest = open[di].name; break; }
}
locPopulation[girl.location] = Math.max(0, (locPopulation[girl.location] || 1) - 1);
placeGirl(girl, dest);
});
/* ── Police roaming ── */
var suspicion = sv.suspicion || 0;
var tier = suspicion >= 75 ? 3 : suspicion >= 50 ? 2 : suspicion >= 25 ? 1 : 0;
var policeConfig = {
"ember": {
stationChance: [1.00, 0.95, 0.80, 0.55],
outChance: [0.00, 0.00, 0.05, 0.10],
patrolTraits: [
[],
["transient"],
["transient", "socialHub"],
["transient", "socialHub", "academic"]
]
},
"jane": {
stationChance: [0.85, 0.55, 0.30, 0.15],
outChance: [0.10, 0.05, 0.05, 0.05],
patrolTraits: [
["transient"],
["transient", "socialHub"],
["transient", "socialHub", "outdoor"],
["transient", "socialHub", "outdoor", "academic"]
]
},
"angel": {
stationChance: [0.75, 0.45, 0.20, 0.10],
outChance: [0.15, 0.10, 0.05, 0.00],
patrolTraits: [
["transient", "socialHub"],
["transient", "socialHub", "academic"],
["transient", "socialHub", "academic", "outdoor"],
["transient", "socialHub", "academic", "outdoor", "intimate"]
]
}
};
policeVars.forEach(function(pv) {
var girl = sv[pv];
if (!girl) return;
var cfg = policeConfig[pv];
var allowedTraits = cfg.patrolTraits[tier] || [];
var patrolPool = sv.locations
.filter(function(l) {
if (l.noPolice) return false; /* police never patrol the mansion */
return allowedTraits.indexOf(l.trait) !== -1
&& (isWE ? l.weekends : l.weekdays);
})
.map(function(l) { return l.name; });
if (Math.random() < cfg.outChance[tier]) {
girl.location = null;
sv.girlLocations[pv] = null;
return;
}
if (Math.random() < cfg.stationChance[tier]) {
if (hasRoom("Police Station")) {
placeGirl(girl, "Police Station");
} else {
var fallback = patrolPool.filter(function(l) { return hasRoom(l); });
if (fallback.length) placeGirl(girl, pickRandom(fallback));
else { girl.location = null; sv.girlLocations[pv] = null; }
}
return;
}
var patrolOpts = patrolPool.filter(function(l) { return hasRoom(l); });
if (!patrolOpts.length) {
if (hasRoom("Police Station")) placeGirl(girl, "Police Station");
else { girl.location = null; sv.girlLocations[pv] = null; }
return;
}
placeGirl(girl, pickRandom(patrolOpts));
});
};/* =========================================================================
§ 10. ACTIVITY SYSTEM
========================================================================= */
window.ACTIVITY_DEFS = {
/* ── EVERYDAY ── */
"Library": { name: "Study Session", icon: "📚", type: "everyday", chance: 0.10, min: 4 },
"Cafeteria": { name: "Lunch Break", icon: "🍽", type: "everyday", chance: 0.10, min: 4 },
"Gym": { name: "Gym Workout", icon: "💪", type: "everyday", chance: 0.10, min: 4 },
"Restaurant": { name: "Dinner Out", icon: "🍷", type: "everyday", chance: 0.10, min: 4 },
"House": { name: "Family Evening", icon: "🏡", type: "everyday", chance: 0.10, min: 4 },
"Arcade": { name: "Arcade Night", icon: "🕹", type: "everyday", chance: 0.35, min: 3 },
"Cinema": { name: "Cinema Night", icon: "🎬", type: "everyday", chance: 0.35, min: 3 },
/* ── WEEKDAY ── */
"School Hallway": { name: "Skipping Class", icon: "🚪", type: "weekday", chance: 0.20, min: 3 },
"Detention Room": { name: "Detention", icon: "🔒", type: "weekday", chance: 0.15, min: 3 },
/* ── WEEKEND ── */
"Cheerleader Track": { name: "Cheerleader Show", icon: "📣", type: "weekend", chance: 0.40, min: 5 },
"Sorority House": { name: "Social Event", icon: "🎊", type: "weekend", chance: 0.40, min: 4 },
"Beach": { name: "Day Out", icon: "🌊", type: "weekend", chance: 0.40, min: 4 },
"Clothing Store": { name: "Shopping Trip", icon: "🛍", type: "weekend", chance: 0.40, min: 4 },
"Spa": { name: "Spa Day Out", icon: "🧖", type: "weekend", chance: 0.30, min: 3 },
"Hotel": { name: "Hotel Gala", icon: "🥂", type: "weekend", chance: 0.25, min: 4 },
"Club": { name: "Club Outing", icon: "🎧", type: "weekend", chance: 0.35, min: 4 },
};
window.rollDailyActivities = function() {
var sv = State.variables;
var isWE = sv.isWeekend;
sv.availableActivities = {};
Object.keys(window.ACTIVITY_DEFS).forEach(function(loc) {
var def = window.ACTIVITY_DEFS[loc];
var eligible = (def.type === "everyday") ||
(def.type === "weekend" && isWE) ||
(def.type === "weekday" && !isWE);
if (!eligible) return;
if (Math.random() < def.chance) {
sv.availableActivities[loc] = def.name;
}
});
};
window.buildSocialChain = function(seeds, max, filter) {
var sv = State.variables;
var result = [];
var visited = {};
/* Deduplicate seeds up front */
seeds.forEach(function(id) {
if (visited[id]) return;
if (!sv[id] || sv[id].arrested) return;
visited[id] = true;
result.push(id);
});
var queue = result.slice();
while (result.length < max && queue.length > 0) {
var nextQueue = [];
var added = false;
for (var qi = 0; qi < queue.length; qi++) {
var c = sv[queue[qi]];
if (!c || !c.connections) continue;
var conns = c.connections.slice().sort(function() { return Math.random() - 0.5; });
for (var ci = 0; ci < conns.length; ci++) {
var cid = conns[ci];
if (visited[cid]) continue;
var cc = sv[cid];
if (!cc || cc.arrested) continue;
if (filter && !filter(cid, cc)) continue;
visited[cid] = true;
result.push(cid);
nextQueue.push(cid);
added = true;
if (result.length >= max) return result;
}
}
queue = nextQueue;
if (!added) break;
}
return result.slice(0, max);
};
window.buildActivityAttendees = function(location) {
var sv = State.variables;
var roster = sv.roster;
var MAX = 7;
function atLoc(loc) {
return roster.filter(function(id) {
var c = sv[id];
return c && c.location === loc && !c.arrested;
});
}
function inSchedule(id, loc) {
var c = sv[id];
if (!c || !c.schedule) return false;
var wd = c.schedule.weekday || [];
var we = c.schedule.weekend || [];
return wd.indexOf(loc) !== -1 || we.indexOf(loc) !== -1;
}
function shuffle(arr) {
return arr.slice().sort(function() { return Math.random() - 0.5; });
}
function unique(arr) {
var seen = {};
return arr.filter(function(id) {
if (seen[id]) return false;
seen[id] = true;
return true;
});
}
var metOnly = function(id, c) { return !!c.met; };
switch (location) {
/* ── LIBRARY ── */
case "Library": {
var teachers = ["adria","adriana","natalie","karlee", "jade", "gabbie", "veruca", "mia", "amber"];
var students = ["vanna","alex","avi","ashly","violet","kyler", "emily", "kailey", "riley", "kenzie", "molly", "chloe"];
/* ── TEACHER SLOT: one available, met, not arrested ── */
var availTeachers = shuffle(teachers.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested;
}));
var teacher = availTeachers.length ? availTeachers[0] : null;
var attendees = teacher ? [teacher] : [];
/* ── STUDENT SLOTS: up to 4 ── */
var availStudents = shuffle(students.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested && attendees.indexOf(id) === -1;
}));
attendees = unique(attendees.concat(availStudents.slice(0, 4)));
return attendees;
}
/* ── CAFETERIA ── */
case "Cafeteria": {
var present = atLoc("Cafeteria").slice();
["christie", "gina"].forEach(function(id) {
var idx = present.indexOf(id);
if (idx !== -1 && Math.random() > 0.30) present.splice(idx, 1);
});
return window.buildSocialChain(present, MAX, metOnly);
}
/* ── SCHOOL HALLWAY (Skipping Class) ── */
case "School Hallway": {
var classRosters = sv.classRosters;
var allStudents = [];
Object.keys(classRosters).forEach(function(k) {
allStudents = allStudents.concat(classRosters[k]);
});
allStudents = unique(allStudents);
var schoolLocs = ["School Hallway", "School Rooftop", "Library",
"Chanel's Class", "Amber's Class", "Adriana's Class",
"Mia's Class", "Veruca's Class", "School Pool"];
var restricted = ["routine-bound", "busy", "homebody"];
var eligible = allStudents.filter(function(id) {
var c = sv[id];
if (!c || !c.met || c.arrested) return false;
if (schoolLocs.indexOf(c.location) === -1) return false;
if (c.corr > 25) return true;
return restricted.indexOf(c.roamTrait) === -1;
});
var count = 3 + Math.floor(Math.random() * 3);
return shuffle(eligible).slice(0, Math.min(count, MAX));
}
/* ── DETENTION ROOM ── */
case "Detention Room": {
/* Students, derived — no hand-written roster.
A girl is a student if her group is flagged `school` in
GROUP_DEFS and she isn't one of the adults the roaming code
already recognises via window.isStudent(). That single
predicate now drives both this pool and the School/Dorms
placement rule, so the two can no longer drift apart.
Staff are excluded by group (School Authority Figures is a
school group but supervises rather than attends), and the
three council/club helpers are pulled out below because they
assist detention rather than serve it. */
var detStudents = (sv.roster || []).filter(function(id) {
if (!window.isStudent(id)) return false;
var c = sv[id];
return c.group !== "School Authority Figures";
});
/* ── PROFESSOR ── */
var professors = ["veruca","mia"];
var professor = professors[Math.floor(Math.random() * professors.length)];
var attendees = [professor];
/* ── ASSISTANT: 40% chance ──
These four help run detention, so they are removed from the
student pool below rather than being eligible to sit in it. */
var DET_HELPERS = ["anya","gabbie","adria","jade"];
var assistants = DET_HELPERS.filter(function(id) {
var c = sv[id];
return c && !c.arrested;
});
if (assistants.length > 0 && Math.random() < 0.40) {
attendees.push(shuffle(assistants)[0]);
}
/* ── STUDENT POOL ── */
var studentPool = detStudents.filter(function(id) {
var c = sv[id];
if (!c || !c.met || c.arrested) return false;
if (attendees.indexOf(id) !== -1) return false;
if (DET_HELPERS.indexOf(id) !== -1) return false; /* they run it */
return true;
});
var usualSuspects = ["uma","ash","rae","vanna","abella"].filter(function(id) {
return studentPool.indexOf(id) !== -1;
});
var corrupted = studentPool.filter(function(id) {
return sv[id].corr > 25;
});
var studentSlots = 3 + Math.floor(Math.random() * 2);
var chosen = [];
if (corrupted.length > 0 && Math.random() < 0.50) {
var anchor = shuffle(corrupted)[0];
chosen.push(anchor);
var friends = (sv[anchor].connections || []).filter(function(id) {
return studentPool.indexOf(id) !== -1 && chosen.indexOf(id) === -1;
});
chosen = chosen.concat(shuffle(friends).slice(0, studentSlots - 1));
if (chosen.length < studentSlots) {
var pad = shuffle(usualSuspects.filter(function(id) {
return chosen.indexOf(id) === -1;
}));
if (!pad.length) pad = shuffle(studentPool.filter(function(id) {
return chosen.indexOf(id) === -1;
}));
chosen = chosen.concat(pad).slice(0, studentSlots);
}
} else {
chosen = shuffle(usualSuspects).slice(0, studentSlots);
if (chosen.length < studentSlots) {
var randStudents = shuffle(studentPool.filter(function(id) {
return chosen.indexOf(id) === -1;
}));
chosen = chosen.concat(randStudents).slice(0, studentSlots);
}
}
return unique(attendees.concat(chosen)).slice(0, MAX);
}
/* ── CHEERLEADER TRACK ── */
case "Cheerleader Track": {
var cheerSet = ["lacy","athena","isabella","blake","marie","abella",
"leah","kailey","alex","harley","uma","aidra","mia"];
var present = atLoc("Cheerleader Track").filter(function(id) { return !!sv[id].met; });
var presCheer = present.filter(function(id) { return cheerSet.indexOf(id) !== -1; });
var presSpect = present.filter(function(id) { return cheerSet.indexOf(id) === -1; });
var cheerTarget = 3 + Math.floor(Math.random() * 3);
if (presCheer.length < cheerTarget) {
var rem = shuffle(cheerSet.filter(function(id) {
return presCheer.indexOf(id) === -1 && sv[id] && !sv[id].arrested;
}));
var fromSched = shuffle(roster.filter(function(id) {
return cheerSet.indexOf(id) === -1 && presCheer.indexOf(id) === -1 &&
inSchedule(id, "Cheerleader Track") && sv[id] && !sv[id].arrested;
}));
presCheer = unique(presCheer.concat(rem).concat(fromSched)).slice(0, cheerTarget);
}
var spectMax = Math.min(MAX - presCheer.length, 4);
var spectTarget = Math.min(2 + Math.floor(Math.random() * 3), spectMax);
if (presSpect.length < spectTarget) {
var specPad = shuffle(roster.filter(function(id) {
return presCheer.indexOf(id) === -1 && presSpect.indexOf(id) === -1 &&
inSchedule(id, "Cheerleader Track") && sv[id] && !sv[id].arrested;
}));
presSpect = unique(presSpect.concat(specPad)).slice(0, spectTarget);
}
return unique(presCheer.concat(presSpect)).slice(0, MAX);
}
/* ── SORORITY HOUSE ── */
case "Sorority House": {
var present = atLoc("Sorority House").filter(function(id) { return !!sv[id].met; });
var fromSched = shuffle(roster.filter(function(id) {
return present.indexOf(id) === -1 && inSchedule(id, "Sorority House") &&
sv[id] && sv[id].met && !sv[id].arrested;
}));
var pool = unique(present.concat(fromSched));
if (pool.length < MAX) {
var classRosters = sv.classRosters;
var allStudents = [];
Object.keys(classRosters).forEach(function(k) {
allStudents = allStudents.concat(classRosters[k]);
});
var students = shuffle(unique(allStudents).filter(function(id) {
return pool.indexOf(id) === -1 && sv[id] && sv[id].met && !sv[id].arrested;
}));
pool = unique(pool.concat(students)).slice(0, MAX);
}
return pool;
}
/* ── GYM ── */
case "Gym": {
var present = atLoc("Gym");
var fromSched = shuffle(roster.filter(function(id) {
return present.indexOf(id) === -1 && inSchedule(id, "Gym") && sv[id] && !sv[id].arrested;
}));
var seeds = unique(present.concat(fromSched)).slice(0, MAX);
return window.buildSocialChain(seeds, MAX, metOnly);
}
/* ── BEACH ── */
case "Beach": {
var present = atLoc("Beach");
var result = window.buildSocialChain(present, MAX, metOnly);
if (result.length < 4) {
var fromSched = shuffle(roster.filter(function(id) {
return result.indexOf(id) === -1 && inSchedule(id, "Beach") && sv[id] && !sv[id].arrested;
}));
result = window.buildSocialChain(unique(result.concat(fromSched)), MAX, metOnly);
}
return result;
}
/* ── CLOTHING STORE ── */
case "Clothing Store": {
var g1g2 = ["jewelz","elsa","emily","lana","kylie",
"eva","harmony","aria","laila","demi",
"marie","claire","karlee","scarlet","isabella",
"riley","kailey","autumn","gabbie","winter","vina","melissa"];
var eligible = roster.filter(function(id) {
var c = sv[id];
if (!c || !c.met || c.arrested) return false;
return g1g2.indexOf(id) !== -1 || c.corr > 25;
});
if (!eligible.length) return [];
var atStore = eligible.filter(function(id) { return sv[id].location === "Clothing Store"; });
var pool = atStore.length > 0 ? atStore : eligible;
var starter = pool[Math.floor(Math.random() * pool.length)];
return window.buildSocialChain([starter], MAX, metOnly);
}
/* ── RESTAURANT ── */
case "Restaurant": {
var anyMet = roster.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested;
});
if (!anyMet.length) return [];
var atRest = anyMet.filter(function(id) { return sv[id].location === "Restaurant"; });
var pool = atRest.length > 0 ? atRest : anyMet;
var starter = pool[Math.floor(Math.random() * pool.length)];
return window.buildSocialChain([starter], MAX, metOnly);
}
/* ── HOUSE (Family Evening) ── */
case "House": {
var g1 = ["emily","jewelz","elsa","lana","kylie","winter"];
var friends = ["aria","eva","melody","kali","vina","melissa"];
var g1AtHome = g1.filter(function(id) {
var c = sv[id];
return c && c.location === "House" && !c.arrested;
});
var g1Away = g1.filter(function(id) {
return g1AtHome.indexOf(id) === -1 && sv[id] && !sv[id].arrested;
});
var pool = unique(g1AtHome.concat(shuffle(g1Away)));
if (pool.length < MAX) {
var availFriends = shuffle(friends.filter(function(id) {
var c = sv[id];
return c && !c.arrested && pool.indexOf(id) === -1;
}));
pool = unique(pool.concat(availFriends)).slice(0, MAX);
}
return pool;
}
/* ── ARCADE NIGHT ── */
case "Arcade": {
/* Use full roster instead of classRosters to avoid excluding
non-student characters (e.g. Vina) who may be physically present */
var outgoing = ["social", "weekendSocial", "restless"];
var present = atLoc("Arcade");
var preferred = roster.filter(function(id) {
var c = sv[id];
if (!c || !c.met || c.arrested) return false;
if (present.indexOf(id) !== -1) return false;
return outgoing.indexOf(c.roamTrait) !== -1 || c.corr > 25;
});
var fallback = roster.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested &&
present.indexOf(id) === -1 &&
preferred.indexOf(id) === -1;
});
var seeds = unique(present.concat(shuffle(preferred)).concat(shuffle(fallback))).slice(0, MAX);
return window.buildSocialChain(seeds, MAX, metOnly);
}
/* ── CINEMA NIGHT ── */
case "Cinema": {
var anyMet = roster.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested;
});
if (!anyMet.length) return [];
var present = atLoc("Cinema");
var pool = present.length > 0 ? present : anyMet;
var starter = pool[Math.floor(Math.random() * pool.length)];
return window.buildSocialChain([starter], 5, metOnly);
}
/* ── SPA DAY OUT ── */
case "Spa": {
var present = atLoc("Spa");
var eligible = roster.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested && present.indexOf(id) === -1;
});
var seeds = unique(present.concat(shuffle(eligible))).slice(0, MAX);
return window.buildSocialChain(seeds, MAX, metOnly);
}
/* ── HOTEL GALA ── */
case "Hotel": {
var galaCrowd = ["momo","autumn","stella","caitlyn",
"nicole","kenna","quinn","megan",
"chanel","amber","adriana","veruca","mia","aidra",
"gina","christie","shazia","kate","skylar","nikki",
"keisha","lily","jane","ember","jessa","winter",
"lacy","athena","vanna","luna","casey","haley","kendra"];
var present = atLoc("Hotel");
var eligible = galaCrowd.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested && present.indexOf(id) === -1;
});
var extras = roster.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested &&
galaCrowd.indexOf(id) === -1 && present.indexOf(id) === -1;
});
var seeds = unique(present.concat(shuffle(eligible)).concat(shuffle(extras))).slice(0, MAX);
return window.buildSocialChain(seeds, MAX, metOnly);
}
/* ── CLUB OUTING ── */
case "Club": {
/* "vanna" and "autumn" were duplicated in the old list — fixed */
var clubRegulars = ["leda","lexi","avery","ash","vanna","blake",
"caprice","abella","leah","rae","kailey","carolina",
"may","autumn"];
var present = atLoc("Club");
var regulars = clubRegulars.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested && present.indexOf(id) === -1;
});
var seeds = unique(present.concat(shuffle(regulars))).slice(0, MAX);
return window.buildSocialChain(seeds, MAX, metOnly);
}
default:
return [];
}
};/* =========================================================================
§ 11. GOALS SYSTEM
========================================================================= */
/* ── GROUP DEFINITIONS ── */
/* GOAL_GROUPS is no longer written by hand. It was a verbatim third copy of
the 94-name membership list — the other two being GroupData's $groups and
the `group:` field on every girl — and all three had to be edited together.
window.buildGroups() (GroupData) derives it from the roster at StoryInit
and rebuilds it whenever the roster changes. Declared here only so that
anything touching it before StoryInit finishes sees an object rather than
undefined. */
window.GOAL_GROUPS = window.GOAL_GROUPS || {};
window.GOAL_SLOT_CAPS = { meet: 2, faction: 2, spread: 2, group: 2, corruption: 4, location: 1, locationCount: 1, classRoster: 1 };
window.SCHOOL_LOCATIONS = ["Chanel's Class","Amber's Class","Adriana's Class","Library","School Hallway","School Rooftop","Cafeteria","Cheerleader Track"];
window.BUSINESS_LOCATIONS = ["Mall","Restaurant","Gym","Sorority House","Beach","Park"];
window.SPREAD_MILESTONES = [10, 15, 20, 25, 30, 35, 40, 50];
window.spreadMilestoneReward = function(threshold) {
if (threshold >= 50) return 5;
if (threshold >= 40) return 4;
if (threshold >= 30) return 3;
if (threshold >= 20) return 2;
return 1;
};
/* The highest corruption a goal may sensibly ask for.
This was derived from parasiteLevel alone, which is the wrong stat. What
actually limits a girl's corruption is getCorrCap() — the global Universal
Threshold upgrades plus her own cap breaks. A player who bought Universal
Threshold I could take girls to 50, but every corruption goal still read
"to 25"; conversely a player who evolved without buying the threshold was
handed goals demanding 50 that were mathematically unreachable.
Take whichever is genuinely achievable. */
window.goalCorrCeiling = function() {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
var byLvl = lvl >= 4 ? 100 : lvl >= 3 ? 75 : lvl >= 2 ? 50 : 25;
var byCap = (typeof window.getCorrCap === "function") ? window.getCorrCap() : 25;
return Math.max(byLvl, byCap);
};
/* ── GOAL LABEL ── */
window.goalLabel = function(type, target) {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
/* The current ceiling, resolved once. `var` is function-scoped, so
declaring it inside a single case and reading it from another would
give "Corr undefined" on every path that did not run that case. */
var threshold = window.goalCorrCeiling();
switch (type) {
/* legacy — kept so pre-existing saves still resolve */
case "individual": {
var c = sv[target];
return c ? "Bring " + c.name + " to Corr " + threshold : "Individual goal";
}
case "meet": {
var c = sv[target];
return c ? "Meet and infect " + c.name : "Meet and infect someone new";
}
case "corruption": {
var c = sv[target.id];
return c ? "Bring " + c.name + " to Corr " + target.threshold : "Corruption goal";
}
case "faction": {
var f = (sv.factions || []).find(function(f) { return f.id === target; });
return f ? "Bring all of " + f.name + " to Corr " + threshold : "Faction goal";
}
case "spread":
/* "Corrupt N girls" never said what corrupt meant. It is the
current ceiling from goalCorrCeiling() — the higher of the
parasite level cap and any purchased threshold — and it rises
as you evolve, so girls who already counted can stop counting.
Say the number. */
return target === "all"
? "Bring every girl to Corr " + threshold
: "Bring " + target + " girls to Corr " + threshold;
case "group": {
var g = window.GOAL_GROUPS[target];
if (g) return "Bring all of " + g.label + " to Corr " + threshold;
/* Fall back to the definition table if the goal outlived a
rebuild (e.g. every member of a mod group was removed). */
var d = window.getGroupDef ? window.getGroupDef(target) : null;
return d ? "Bring all of " + d.label + " to Corr " + threshold : "Group goal";
}
case "location":
return "Dominate " + target;
case "locationCount":
return "Dominate " + target + " locations";
case "classRoster": {
/* Class goals cap at 75 rather than following the ceiling. */
var classThreshold = Math.min(75, threshold);
return "Bring " + target + "'s class to Corr " + classThreshold;
}
default: return "Unknown goal";
}
};
/* ── GOAL REWARD LABEL ── */
window.goalRewardLabel = function(type, target) {
switch (type) {
case "individual": return "+8 parasites";
case "meet": return "+3 parasites";
case "corruption": return "+8 parasites · capacity bonus";
case "faction": return "+10 parasites · dominate location";
case "spread":
return target === "all" ? "Infection Power +5" : "Infection Power +" + window.spreadMilestoneReward(target);
case "group": switch (target) {
case "G1": return "+1 parasite / day";
case "G2": return "No suspicion: intimate locations";
case "G3": return "Permanent nest (school)";
case "G4": return "All school locations dominated";
case "G5": return "No suspicion: school locations";
case "G6": return "All business locations dominated";
case "G7": return "Suspicion → 0, permanently";
default: return "+5 parasites"; /* custom / mod group */
}
case "location": return "+5 parasites · dominate location";
case "locationCount": return "+8 parasites · hivemind +2";
case "classRoster": return "+6 parasites · nest cap +1";
default: return "";
}
};
/* ── GOAL PROGRESS ── */
window.getGoalProgress = function(goal) {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
switch (goal.type) {
case "individual": {
var c = sv[goal.target];
var threshold = window.goalCorrCeiling();
var cur = c ? Math.min(c.corr, threshold) : 0;
return { current: cur, target: threshold, pct: threshold > 0 ? Math.round(cur / threshold * 100) : 0 };
}
/* Two steps: meet her, then infect her. Both required. */
case "meet": {
var mc = sv[goal.target];
var mdone = 0;
if (mc && mc.met) mdone++;
if (mc && mc.infected) mdone++;
return { current: mdone, target: 2, pct: Math.round(mdone / 2 * 100) };
}
case "corruption": {
var c = sv[goal.target.id];
var thr = goal.target.threshold;
var cur = c ? Math.min(c.corr, thr) : 0;
return { current: cur, target: thr, pct: Math.round(cur / thr * 100) };
}
case "faction": {
var f = (sv.factions || []).find(function(f) { return f.id === goal.target; });
if (!f || !f.members.length) return { current: 0, target: 1, pct: 0 };
var threshold = window.goalCorrCeiling();
var done = f.members.filter(function(id) { return sv[id] && sv[id].corr >= threshold; }).length;
return { current: done, target: f.members.length, pct: Math.round(done / f.members.length * 100) };
}
case "spread": {
var threshold = window.goalCorrCeiling();
var done = sv.roster.filter(function(id) { return sv[id] && sv[id].corr >= threshold; }).length;
var tgt = goal.target === "all" ? sv.roster.length : goal.target;
return { current: done, target: tgt, pct: Math.min(100, Math.round(done / tgt * 100)) };
}
case "group": {
var grp = window.GOAL_GROUPS[goal.target];
var members = grp ? grp.members : sv.roster;
var threshold = window.goalCorrCeiling();
var done = members.filter(function(id) { return sv[id] && sv[id].corr >= threshold; }).length;
return { current: done, target: members.length, pct: Math.round(done / members.length * 100) };
}
case "location": {
var dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
var done = dominated.indexOf(goal.target) !== -1 ? 1 : 0;
return { current: done, target: 1, pct: done * 100 };
}
case "locationCount": {
var dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
return { current: dominated.length, target: goal.target, pct: Math.min(100, Math.round(dominated.length / goal.target * 100)) };
}
case "classRoster": {
var roster = sv.classRosters && sv.classRosters[goal.target];
if (!roster || !roster.length) return { current: 0, target: 1, pct: 0 };
var threshold = Math.min(75, window.goalCorrCeiling());
var done = roster.filter(function(id) { return sv[id] && sv[id].corr >= threshold; }).length;
return { current: done, target: roster.length, pct: Math.round(done / roster.length * 100) };
}
default: return { current: 0, target: 1, pct: 0 };
}
};
/* ── BUILD GOAL POOL ── */
window.buildGoalPool = function() {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
var pool = [];
function alreadyTracked(type, target) {
var key = String(target);
/* Permanent history first — a completed objective never returns */
if (window.hasCompletedGoal(type, target)) return true;
return (sv.goals || []).some(function(g) { return g.type === type && String(g.target) === key; }) ||
(sv.goalsCompleted || []).some(function(g) { return g.type === type && String(g.target) === key; });
}
var threshold = window.goalCorrCeiling();
/* ── Corruption threshold (specific girl + her NEXT threshold) ──
Replaces the old "individual" type, which was the same goal without
an explicit target number. Only the next unreached tier is offered,
so one girl never occupies several slots at once. */
sv.roster.forEach(function(id) {
var c = sv[id];
/* Met is enough — an uninfected girl at corr 0 is a valid target.
Requiring .infected meant no goal existed until you'd already
infected her, which inverted the point of having a goal. */
if (!c || !c.met) return;
var next = null;
[25, 50, 75, 100].some(function(tv) {
if (tv > threshold) return true; /* stop: beyond current cap */
if (c.corr < tv) { next = tv; return true; }
return false;
});
if (next === null) return;
var tgt = { id: id, threshold: next };
if (window.hasCompletedGoal("corruption", tgt)) return;
var dup = (sv.goals || []).some(function(g) {
return g.type === "corruption" && g.target &&
g.target.id === id && g.target.threshold === next;
});
if (dup) return;
pool.push({ type: "corruption", target: tgt, _key: id + "_" + next });
});
/* ── Make Contact: meet an unmet girl, then infect her ── */
sv.roster.forEach(function(id) {
var c = sv[id];
if (!c || c.met || c.arrested) return;
if (window.hasCompletedGoal("meet", id)) return;
if ((sv.goals || []).some(function(g) { return g.type === "meet" && g.target === id; })) return;
if (c.meetingMethod === "contact") {
var reachable = window.getContactPool(id).some(function(cid) {
var cc = sv[cid]; return cc && cc.met;
});
if (!reachable) return;
}
pool.push({ type: "meet", target: id });
});
/* ── Type 2: Faction ── */
(sv.factions || []).forEach(function(f) {
var leader = sv[f.leader];
if (!leader || !leader.met) return;
if (alreadyTracked("faction", f.id)) return;
pool.push({ type: "faction", target: f.id });
});
/* ── Type 3: Spread milestones ── */
var totalAtThreshold = sv.roster.filter(function(id) { return sv[id] && sv[id].corr >= threshold; }).length;
window.SPREAD_MILESTONES.forEach(function(m) {
if (totalAtThreshold >= m) return;
if (alreadyTracked("spread", m)) return;
pool.push({ type: "spread", target: m });
});
/* ── Type 4: Group ── */
Object.keys(window.GOAL_GROUPS).forEach(function(gid) {
var grp = window.GOAL_GROUPS[gid];
var allDone = grp.members.every(function(id) { return sv[id] && sv[id].corr >= threshold; });
if (allDone) return;
if (alreadyTracked("group", gid)) return;
pool.push({ type: "group", target: gid });
});
/* ── Type: Location domination (specific) — level 2+ ── */
if (lvl >= 2) {
var dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
(sv.locations || []).forEach(function(l) {
if (!l.unlocked) return;
if (l.noGoal) return; /* Harem Mansion is not a target */
if (dominated.indexOf(l.name) !== -1) return;
if (alreadyTracked("location", l.name)) return;
pool.push({ type: "location", target: l.name });
});
}
/* ── Type: Location count milestones — level 2+ ── */
if (lvl >= 2) {
var dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
[3, 5, 8, 10, 15].forEach(function(n) {
if (dominated.length >= n) return;
if (alreadyTracked("locationCount", n)) return;
pool.push({ type: "locationCount", target: n });
});
}
/* ── Type: Class roster — level 2+ ── */
if (lvl >= 2 && sv.classRosters) {
var thrClass = lvl >= 3 ? 75 : 50;
Object.keys(sv.classRosters).forEach(function(teacher) {
var roster = sv.classRosters[teacher];
var qualified = roster.filter(function(id) { return sv[id] && sv[id].corr >= thrClass; }).length;
if (qualified === roster.length) return; /* already done */
if (qualified === 0) return; /* not started — don't show yet */
if (alreadyTracked("classRoster", teacher)) return;
pool.push({ type: "classRoster", target: teacher });
});
}
return pool;
};
/* ── APPLY GOAL REWARD ── */
window.applyGoalReward = function(goal, log) {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
var b = sv.goalBonuses || {};
switch (goal.type) {
case "individual":
sv.parasite = (sv.parasite || 0) + 8;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +8 parasites.</span>');
break;
case "meet":
sv.parasite = (sv.parasite || 0) + 3;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +3 parasites.</span>');
break;
case "corruption": {
sv.parasite = (sv.parasite || 0) + 8;
/* Bonus: small capacity increase */
var caps = window.PARASITE_LEVEL_CAPS && window.PARASITE_LEVEL_CAPS[lvl];
if (caps && (sv.hivemindCap || 5) < caps.hivemind) {
sv.hivemindCap = (sv.hivemindCap || 5) + 1;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +5 parasites · Hivemind +1.</span>');
} else if (caps && (sv.nestCap || 2) < caps.nestCap) {
sv.nestCap = (sv.nestCap || 2) + 1;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +5 parasites · Nest Cap +1.</span>');
} else {
sv.parasite += 3; /* extra parasites if caps are maxed */
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +8 parasites.</span>');
}
break;
}
case "faction": {
sv.parasite = (sv.parasite || 0) + 10;
var f = (sv.factions || []).find(function(f) { return f.id === goal.target; });
if (f && f.homeLocation && b.corruptedLocations && b.corruptedLocations.indexOf(f.homeLocation) === -1) {
b.corruptedLocations.push(f.homeLocation);
log.push('<span style="color:#bd59ff">☣ <b>' + f.homeLocation + '</b> is now dominated.</span>');
}
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +10 parasites.</span>');
break;
}
case "spread": {
var bonus = goal.target === "all" ? 5 : window.spreadMilestoneReward(goal.target);
sv.infectionPower = (sv.infectionPower || 1) + bonus;
b.upgradeBonus = (b.upgradeBonus || 0) + bonus;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! Infection Power +' + bonus + '.</span>');
break;
}
case "group":
switch (goal.target) {
case "G1":
b.passiveParasite = (b.passiveParasite || 0) + 1;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +1 parasite/day.</span>');
break;
case "G2":
b.noSuspicionIntimate = true;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! No suspicion in intimate locations.</span>');
break;
case "G3": {
var placed = window.SCHOOL_LOCATIONS.find(function(l) { return sv.nests[l] && sv.nests[l].level === 0; });
if (placed) {
sv.nests[placed].level = 1;
sv.nests[placed].days = 99999;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! Permanent nest at ' + placed + '.</span>');
}
break;
}
case "G4":
window.SCHOOL_LOCATIONS.forEach(function(l) {
if (b.corruptedLocations.indexOf(l) === -1) b.corruptedLocations.push(l);
});
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! All school locations dominated.</span>');
break;
case "G5":
b.noSuspicionSchool = true;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! No suspicion from school locations.</span>');
break;
case "G6":
window.BUSINESS_LOCATIONS.forEach(function(l) {
if (b.corruptedLocations.indexOf(l) === -1) b.corruptedLocations.push(l);
});
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! All business locations dominated.</span>');
break;
case "G7":
sv.suspicion = 0;
b.noSuspicionAll = true;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! Suspicion neutralised permanently.</span>');
break;
default:
/* A group with no bespoke reward — a custom one declared
by a girl outside GROUP_DEFS. It still completes and
still pays, just generically, rather than falling
through in silence with nothing granted. */
sv.parasite = (sv.parasite || 0) + 5;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +5 parasites.</span>');
break;
}
break;
case "location": {
sv.parasite = (sv.parasite || 0) + 5;
if (b.corruptedLocations && b.corruptedLocations.indexOf(goal.target) === -1) {
b.corruptedLocations.push(goal.target);
log.push('<span style="color:#bd59ff">☣ <b>' + goal.target + '</b> is now dominated.</span>');
}
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +5 parasites.</span>');
break;
}
case "locationCount": {
sv.parasite = (sv.parasite || 0) + 8;
sv.hivemindCap = (sv.hivemindCap || 5) + 2;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +8 parasites · Hivemind +2.</span>');
break;
}
case "classRoster": {
sv.parasite = (sv.parasite || 0) + 6;
sv.nestCap = (sv.nestCap || 2) + 1;
log.push('<span style="color:#bd59ff">🎯 <b>' + goal.label + '</b> complete! +6 parasites · Nest Cap +1.</span>');
break;
}
}
sv.goalJustCompleted = true;
};
/* ── ROLL NEW GOALS ── */
window.rollNewGoals = function(force, onlyTypes, log) {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
if (!force && sv.day - (sv.lastGoalDay || 0) < 5) return [];
var pool = window.buildGoalPool();
if (onlyTypes && onlyTypes.length) {
pool = pool.filter(function(p) { return onlyTypes.indexOf(p.type) !== -1; });
}
var current = sv.goals || [];
var caps = window.GOAL_SLOT_CAPS;
/* Count current goals by type */
var countByType = {};
current.forEach(function(g) {
countByType[g.type] = (countByType[g.type] || 0) + 1;
});
pool.sort(function() { return Math.random() - 0.5; });
/* How many NEW goals a single roll may hand out.
This used to be unbounded: the loop walked the whole pool and added a
goal for every type that was under its cap. On a quiet day that is one
or two, but the moment several slots freed at once — a few goals
completing together, or the pool suddenly filling because you met a lot
of people — it granted the entire remaining allowance in one night. The
result was the reported behaviour: three goals one day, everything the
next.
Two at a time keeps the board moving without ever dumping a full set. */
var MAX_NEW_PER_ROLL = 2;
var added = [];
pool.forEach(function(pick) {
if (added.length >= MAX_NEW_PER_ROLL) return;
var typeKey = pick.type;
var have = (countByType[typeKey] || 0) + added.filter(function(g) { return g.type === typeKey; }).length;
if (have >= (caps[typeKey] || 1)) return;
added.push({
id: sv.nextGoalId++,
type: pick.type,
label: window.goalLabel(pick.type, pick.target),
target: pick.target,
complete: false,
dayAdded: sv.day || 0
});
});
/* The per-type counter inside the loop was also called `current`, which
shadowed the goal array. That was harmless — the inner `var` is scoped
to the callback, so the outer array survived — but reading it took a
double-take. It is `have` now. */
sv.goals = current.concat(added);
sv.lastGoalDay = sv.day || 0;
/* Announce anything new. New goals used to appear on the Goals screen
with nothing said about it, so unless the player happened to open that
page they never learned an objective had arrived. processDayEnd passes
its log in; the mid-day callers (MeetingWrapper, FactionParty) pass
nothing and stay silent, because they are already showing a scene. */
if (log && added.length) {
added.forEach(function(g) {
log.push('<span style="color:#44aaff">\u2726 New objective: <b>' +
g.label + '</b></span>');
});
}
return added;
};
/* ── CHECK GOAL COMPLETION ── */
window.checkGoalCompletion = function(log) {
var sv = State.variables;
if (!sv.goals) sv.goals = [];
if (!sv.goalsCompleted) sv.goalsCompleted = [];
var toRemove = [];
sv.goals.forEach(function(goal) {
if (goal.complete) return;
/* Discard faction goals if faction no longer exists */
if (goal.type === "faction") {
var fStillExists = (sv.factions || []).some(function(f) { return f.id === goal.target; });
if (!fStillExists) { toRemove.push(goal.id); return; }
}
/* Discard Make Contact goals if the target is arrested — she can
never be infected, so the goal would hold its slot forever. */
if (goal.type === "meet") {
var mt = sv[goal.target];
if (!mt || mt.arrested) { toRemove.push(goal.id); return; }
}
var prog = window.getGoalProgress(goal);
if (prog.pct < 100) return;
goal.complete = true;
window.applyGoalReward(goal, log);
window.recordGoalCompleted(goal);
sv.goalsCompleted.push(goal);
toRemove.push(goal.id);
});
if (toRemove.length > 0) {
sv.goals = sv.goals.filter(function(g) { return toRemove.indexOf(g.id) === -1; });
/* Only corruption goals refill automatically — they are the
moment-to-moment objective. Every other type leaves its slot
empty until the player spends parasites to reroll it. */
window.rollNewGoals(true, ["corruption", "meet"], log);
}
};
/* ── CHECK CORRUPTED LOCATIONS (faction leader hits threshold) ── */
window.checkCorruptedLocations = function(log) {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
if (!sv.goalBonuses) return;
var b = sv.goalBonuses;
var threshold = lvl >= 4 ? 100 : lvl >= 3 ? 75 : 50;
(sv.factions || []).forEach(function(f) {
var leader = sv[f.leader];
if (!leader || leader.corr < threshold || !f.homeLocation) return;
if (b.corruptedLocations.indexOf(f.homeLocation) !== -1) return;
b.corruptedLocations.push(f.homeLocation);
log.push('<span style="color:#bd59ff">☣ <b>' + f.homeLocation + '</b> falls under the parasite\'s influence.</span>');
});
};
/* ── INIT GOALS ── */
window.initGoals = function() {
var sv = State.variables;
sv.goals = [];
sv.goalsCompleted = [];
sv.nextGoalId = 100;
sv.lastGoalDay = 0;
sv.goalJustCompleted = false;
sv.goalHistory = {};
var pool = window.buildGoalPool();
["corruption", "meet", "spread", "group"].forEach(function(type) {
var eligible = pool.filter(function(p) { return p.type === type; });
if (!eligible.length) return;
var pick = eligible[Math.floor(Math.random() * eligible.length)];
sv.goals.push({
id: sv.nextGoalId++,
type: pick.type,
label: window.goalLabel(pick.type, pick.target),
target: pick.target,
complete: false,
dayAdded: 0
});
});
};
/* =========================================================================
GOAL HISTORY — permanent record of what has been completed
goalsCompleted can be trimmed for display, so we keep a separate
Set-like index that is never pruned. Survives across the whole run.
========================================================================= */
window.goalKey = function(type, target) {
if (type === "corruption" && target && typeof target === "object") {
return "corruption:" + target.id + "_" + target.threshold;
}
return type + ":" + String(target);
};
window.hasCompletedGoal = function(type, target) {
var done = State.variables.goalHistory || {};
return !!done[window.goalKey(type, target)];
};
window.recordGoalCompleted = function(goal) {
var sv = State.variables;
if (!sv.goalHistory) sv.goalHistory = {};
sv.goalHistory[window.goalKey(goal.type, goal.target)] = (sv.day || 0);
};
/* =========================================================================
REROLL A GOAL — costs parasites, swaps one goal for another of a
different target. Returns { ok, msg }.
========================================================================= */
window.GOAL_REROLL_COST = 5;
window.rerollGoal = function(goalId) {
var sv = State.variables;
var cost = window.GOAL_REROLL_COST;
var idx = (sv.goals || []).findIndex(function(g) { return g.id === goalId; });
if (idx === -1) return { ok: false, msg: "Goal not found." };
if ((sv.parasite || 0) < cost) {
return { ok: false, msg: "Need " + cost + " parasites to reroll." };
}
var oldGoal = sv.goals[idx];
/* Candidates: same type, different target, never completed before */
var pool = window.buildGoalPool().filter(function(p) {
if (p.type !== oldGoal.type) return false;
if (window.goalKey(p.type, p.target) === window.goalKey(oldGoal.type, oldGoal.target)) return false;
if (window.hasCompletedGoal(p.type, p.target)) return false;
return true;
});
/* Fall back to any type if this one is exhausted */
if (!pool.length) {
pool = window.buildGoalPool().filter(function(p) {
if (window.hasCompletedGoal(p.type, p.target)) return false;
var caps = window.GOAL_SLOT_CAPS;
var count = sv.goals.filter(function(g) {
return g.type === p.type && g.id !== goalId;
}).length;
return count < (caps[p.type] || 1);
});
}
if (!pool.length) return { ok: false, msg: "No other objectives available." };
var pick = pool[Math.floor(Math.random() * pool.length)];
sv.parasite -= cost;
sv.goals[idx] = {
id: sv.nextGoalId++,
type: pick.type,
label: window.goalLabel(pick.type, pick.target),
target: pick.target,
complete: false,
dayAdded: sv.day || 0
};
return { ok: true, msg: "Rerolled for " + cost + " parasites." };
};
/* getOpenSlots() and buyNewGoal() lived here. The Goals screen offered a paid
"Commission" button for every empty slot; it did not work reliably and the
slots refill from the nightly roll anyway, so both the UI and these two
functions are gone. GOAL_REROLL_COST is still used by the Reroll button. */
/* =========================================================================
CONTACT MEETINGS
A contact girl needs ONE of her connections met and at corruption 25+.
That connection does NOT have to be present — knowing her is enough.
The first qualifying connection becomes the permanent introducer and is
remembered in $contactIntroducer, so she stays introduced even if the
introducer is later arrested or her corruption drops.
Duos are met as a pair. Either girl's connections can unlock both, and
the meeting fires at their shared location.
========================================================================= */
window.CONTACT_DUOS = {
"lulu": { partner: "molly", location: "Cinema" },
"molly": { partner: "lulu", location: "Cinema" },
"madi": { partner: "kenzie", location: "Arcade" },
"kenzie": { partner: "madi", location: "Arcade" }
};
/* Everyone whose connections can unlock this girl — includes a duo partner's. */
window.getContactPool = function(id) {
var sv = State.variables;
var c = sv[id];
if (!c) return [];
var pool = (c.connections || []).slice();
var duo = window.CONTACT_DUOS[id];
if (duo) {
var p = sv[duo.partner];
if (p) (p.connections || []).forEach(function(cid) {
if (pool.indexOf(cid) === -1) pool.push(cid);
});
/* the partner herself is not an introducer */
pool = pool.filter(function(cid) { return cid !== id && cid !== duo.partner; });
}
return pool;
};
/* The introducer, if one has been earned. Locked in on first qualification. */
window.getContactIntroducer = function(id) {
var sv = State.variables;
if (!sv.contactIntroducer) sv.contactIntroducer = {};
/* Already introduced — stays introduced, whatever happened since. */
if (sv.contactIntroducer[id]) return sv.contactIntroducer[id];
var pool = window.getContactPool(id);
for (var i = 0; i < pool.length; i++) {
var cc = sv[pool[i]];
if (cc && cc.met && cc.corr >= 25) {
sv.contactIntroducer[id] = pool[i]; /* first qualifier wins */
/* a duo shares its introducer */
var duo = window.CONTACT_DUOS[id];
if (duo && !sv.contactIntroducer[duo.partner]) {
sv.contactIntroducer[duo.partner] = pool[i];
}
return pool[i];
}
}
return null;
};
window.canMeetContact = function(id) {
return !!window.getContactIntroducer(id);
};
/* Where the meeting happens. Duos meet at their shared spot; a solo contact
girl is met wherever you find her. */
window.getContactLocation = function(id) {
var duo = window.CONTACT_DUOS[id];
return duo ? duo.location : null;
};
/* =========================================================================
MEETING HINTS — where can an unmet girl be found?
========================================================================= */
window.getMeetingHint = function(id) {
var sv = State.variables;
var c = sv[id];
if (!c) return "";
/* Already met — the remaining half of the goal is the infection. */
if (c.met && !c.infected) {
if (window.hivemindFull && window.hivemindFull())
return "Met — hivemind is full, free a slot before you can infect her";
return "Met — now infect her";
}
if (c.met && c.infected) return "Done";
var method = c.meetingMethod;
if (method === "group") {
var gm = (sv.groupMeetings || []).find(function(g) {
return g.members && g.members.indexOf(id) !== -1;
});
if (gm) return "Group meeting · " + gm.location;
}
if (method === "contact") {
var duoLoc = window.getContactLocation(id);
var introId = window.getContactIntroducer(id);
if (introId && sv[introId]) {
var via = sv[introId].name + " mentioned you";
if (duoLoc) return via + " — find them at the " + duoLoc;
var a2 = c.schedule && c.schedule.anchor;
var wh = a2 ? (a2.weekday || a2.weekend) : null;
return wh ? via + " — she's usually at " + wh : via;
}
/* Not unlocked yet: name someone you already know who could do it. */
var pool = window.getContactPool(id);
var known = pool.filter(function(cid) {
var cc = sv[cid]; return cc && cc.met;
});
if (known.length) {
known.sort(function(a, b) { return (sv[b].corr || 0) - (sv[a].corr || 0); });
var best = sv[known[0]];
return "Corrupt " + best.name + " to 25 for an introduction";
}
return "Needs an introduction — you don't know anyone who knows her";
}
var a = c.schedule && c.schedule.anchor;
if (a) {
if (a.weekday && a.weekend && a.weekday !== a.weekend)
return a.weekday + " (weekdays) · " + a.weekend + " (weekends)";
return a.weekday || a.weekend || "";
}
return "";
};
window.getMeetingLocations = function(id) {
var sv = State.variables, c = sv[id];
if (!c) return [];
var duoLoc = window.getContactLocation(id);
if (duoLoc) return [duoLoc];
if (c.meetingMethod === "group") {
var gm = (sv.groupMeetings || []).find(function(g) {
return g.members && g.members.indexOf(id) !== -1;
});
if (gm) return [gm.location];
}
var out = [], a = c.schedule && c.schedule.anchor;
if (a) { if (a.weekday) out.push(a.weekday); if (a.weekend && a.weekend !== a.weekday) out.push(a.weekend); }
return out;
};/* =========================================================================
§ 9. FACTION SYSTEM — CORE
-------------------------------------------------------------------------
Part 1 of 4. Split out of the original JS-Factions, which had reached
2,000+ lines. Load order in StoryInit matters:
JS-Factions-Core -> JS-Factions-Events ->
JS-Factions-Clash -> JS-Factions-Directives
Each is eval'd separately, so nothing may rely on another file's
top-level const. Shared tuning values live on window.FACTION_CFG in
Core and are read from there everywhere else.
========================================================================= */
/* ── CONSTANTS ── */
/* Shared tuning values. These were top-level `const`s, which cannot cross an
eval boundary — the other three files would throw ReferenceError. They live
on window now so every part can read them. */
window.FACTION_CFG = {
STRUCTURAL_COOLDOWN: 7, /* days between growth/expulsion/shift */
RARE_COOLDOWN: 14, /* days between merge/split/disband */
PROTECTION_WINDOW: 7, /* days new factions are stable */
PROTECTION_MIN: 40, /* stability floor during protection */
HISTORY_DAYS: 14, /* days of location history kept */
HOME_MIN_VISITS: 4, /* sightings needed to claim a home */
TERRITORY_MAX: 2, /* max factions sharing a home loc */
TERRITORY_CLASH: 7 /* days before contested loc clashes */
};
/* Local aliases keep the rest of this file readable. */
var FACTION_STRUCTURAL_COOLDOWN = window.FACTION_CFG.STRUCTURAL_COOLDOWN;
var FACTION_RARE_COOLDOWN = window.FACTION_CFG.RARE_COOLDOWN;
var FACTION_PROTECTION_WINDOW = window.FACTION_CFG.PROTECTION_WINDOW;
var FACTION_PROTECTION_MIN = window.FACTION_CFG.PROTECTION_MIN;
var FACTION_HISTORY_DAYS = window.FACTION_CFG.HISTORY_DAYS;
var FACTION_HOME_MIN_VISITS = window.FACTION_CFG.HOME_MIN_VISITS;
var TERRITORY_MAX_PER_LOC = window.FACTION_CFG.TERRITORY_MAX;
var TERRITORY_CLASH_AFTER = window.FACTION_CFG.TERRITORY_CLASH;
/* ── ID ALLOCATOR ────────────────────────────────────────────────────────
BUGFIX: $nextFactionId shipped as 7 while the 8 starting factions already
use ids 1–8, so the next two factions created collided with Lulu's Friends
and Kenzie's Friends. Anything keyed by faction.id — pendingParties,
territoryConflicts, rivalOf, the Factions UI — then hit the wrong faction.
Never read sv.nextFactionId directly. This allocator repairs a bad or
missing counter from the live faction list, so old saves self-heal.
────────────────────────────────────────────────────────────────────── */
window.allocFactionId = function() {
let sv = State.variables;
if (!sv.factions) sv.factions = [];
let maxUsed = 0;
sv.factions.forEach(function(f) {
let n = Number(f.id);
if (!isNaN(n) && n > maxUsed) maxUsed = n;
});
let next = Number(sv.nextFactionId);
if (isNaN(next) || next <= maxUsed) next = maxUsed + 1;
sv.nextFactionId = next + 1;
return next;
};
/* ── VISIBILITY FILTER ───────────────────────────────────────────────────
0 = leader unmet → no log entry at all
1 = leader met, some members unmet → generic names
2 = all members met → full names
────────────────────────────────────────────────────────────────────── */
window.getFactionVisibility = function(faction) {
let sv = State.variables;
/* A group is known to the player once they know ANYBODY in it — not
specifically its leader. Keying on the leader meant a faction full of
girls you knew went completely dark the moment an unmet girl took over,
and a group like Kenzie's stayed invisible even after you'd met half of
it. An unmet leader is perfectly fine; you just hear about the group
through the members you do know. */
let known = faction.members.some(id => sv[id] && sv[id].met);
if (!known) return 0;
let allMet = faction.members.every(id => sv[id] && sv[id].met);
return allMet ? 2 : 1;
};
/* Display name for a faction.
faction.name is always "<Leader>'s Friends", so it cannot be printed when
the leader is a stranger — it would name a girl the player has never seen.
In that case the group is simply "a group": you know it exists, because you
know somebody in it, but not whose it is. */
window.factionDisplayName = function(faction) {
var sv = State.variables;
var leader = sv[faction.leader];
if (leader && leader.met) return faction.name;
return "a group";
};
/* Sentence-initial form, so a line doesn't start with a lowercase "a group". */
window.factionDisplayNameCap = function(faction) {
var n = window.factionDisplayName(faction);
return n === "a group" ? "A group" : n;
};
/* Helper: push a log entry respecting visibility.
fullMsg = shown when vis 2 (all names known)
partialMsg = shown when vis 1 (some unknown, optional — falls back to fullMsg)
Tier 0: nothing pushed. */
window.factionLog = function(log, faction, fullMsg, partialMsg) {
let vis = window.getFactionVisibility(faction);
if (vis === 0) return;
log.push(vis === 2 ? fullMsg : (partialMsg || fullMsg));
};
/* ── STANCE (revised) ─────────────────────────────────────────────────────
Derived from how many members are infected/corrupted.
Evaluated sequentially — later conditions override earlier ones.
────────────────────────────────────────────────────────────────────── */
window.updateFactionStance = function(faction) {
var sv = State.variables;
var members = faction.members;
if (!members || members.length === 0) return;
var infected = members.filter(function(id) { var c = sv[id]; return c && c.infected; });
var atCorr25 = members.filter(function(id) { var c = sv[id]; return c && c.corr >= 25; });
var atCorr50 = members.filter(function(id) { var c = sv[id]; return c && c.corr >= 50; });
var leader = sv[faction.leader];
var majority = Math.ceil(members.length * 0.5);
var stance = "neutral";
if (infected.length >= 1) {
stance = "uneasy";
}
if (infected.length >= 2 || atCorr50.length >= 1) {
stance = "receptive";
}
if (atCorr25.length >= majority ||
(leader && leader.corr >= 50 && atCorr50.length >= 2)) {
stance = "enthralled";
}
if (leader && leader.corr >= 75) {
stance = "dominated";
}
faction.stance = stance;
};
/* ── LOCATION HISTORY ────────────────────────────────────────────────────
Track where members are each day. Prune entries older than 14 days.
────────────────────────────────────────────────────────────────────── */
window.updateFactionLocationHistory = function(faction) {
let sv = State.variables;
let day = sv.day;
if (!faction.locationHistory) faction.locationHistory = [];
/* Prune old entries */
faction.locationHistory = faction.locationHistory.filter(function(e) {
return (day - e.day) < FACTION_HISTORY_DAYS;
});
/* Record each member's location today */
faction.members.forEach(function(id) {
let c = sv[id];
if (c && c.location) {
faction.locationHistory.push({ loc: c.location, day: day });
}
});
};
/* ── HOME LOCATION ───────────────────────────────────────────────────────
Most frequently visited location across all members in recent history.
Only locations with trait outdoor/socialHub/transient/academic/intimate
qualify — Police Station and The Lab never become home locations.
────────────────────────────────────────────────────────────────────── */
window.deriveFactionHomeLocation = function(faction) {
/* A home location is claimed ONCE and then kept for the life of the
faction. It is the place the group is known to gather — it should not
drift because a couple of members happened to spend a week elsewhere.
Only a faction that has never established one is still looking. */
if (faction.homeLocation) return faction.homeLocation;
if (!faction.locationHistory || !faction.locationHistory.length) return null;
let excluded = ["Police Station", "The Lab"];
let counts = {};
/* Locations flagged noFaction can never become a base — the Harem
Mansion is yours, not a gathering place a group can claim. */
let noFaction = (State.variables.locations || [])
.filter(function(l) { return l.noFaction; })
.map(function(l) { return l.name; });
faction.locationHistory.forEach(function(e) {
if (excluded.indexOf(e.loc) !== -1) return;
if (noFaction.indexOf(e.loc) !== -1) return;
counts[e.loc] = (counts[e.loc] || 0) + 1;
});
let best = null, bestCount = 0;
Object.keys(counts).forEach(function(loc) {
if (counts[loc] > bestCount) {
bestCount = counts[loc];
best = loc;
}
});
/* Don't claim a home off one or two stray sightings. The group has to
actually keep turning up somewhere before it counts as their place. */
if (bestCount < FACTION_HOME_MIN_VISITS) return null;
return best;
};
/* ── RELOCATE A FACTION ──────────────────────────────────────────────────
The only way a home location changes. Clears the claim and the history
so the faction starts looking for a new place from scratch.
Used when a faction loses its territory in a clash.
────────────────────────────────────────────────────────────────────── */
window.clearFactionHome = function(faction) {
if (!faction) return;
faction.homeLocation = null;
faction.locationHistory = [];
};
/* ── STABILITY TICK ──────────────────────────────────────────────────────
Runs daily. Adjusts stability based on cohesion factors.
────────────────────────────────────────────────────────────────────── */
window.tickFactionStability = function(faction) {
let sv = State.variables;
let members = faction.members;
let day = sv.day;
if (!faction.stability) faction.stability = 50;
/* ── INCREASES ── */
/* Base longevity tick */
faction.stability = Math.min(100, faction.stability + 1);
/* Co-location bonus: pairs sharing a location today */
let locGroups = {};
members.forEach(function(id) {
let c = sv[id];
if (c && c.location) {
locGroups[c.location] = (locGroups[c.location] || 0) + 1;
}
});
let colocPairs = 0;
Object.values(locGroups).forEach(function(count) {
if (count >= 2) colocPairs += Math.floor(count / 2);
});
/* +2 per co-located pair, capped at +4 total */
faction.stability = Math.min(100, faction.stability + Math.min(colocPairs * 2, 4));
/* Home location nest bonus */
let homeLoc = faction.homeLocation;
if (homeLoc) {
let nest = sv.nests[homeLoc];
if (nest && nest.level > 0) {
let nestBonus = nest.level >= 5 ? 3 : nest.level >= 3 ? 2 : 1;
faction.stability = Math.min(100, faction.stability + nestBonus);
}
}
/* ── DECREASES ── */
/* Corr variance penalty */
if (members.length >= 2) {
let corrs = members.map(id => sv[id] ? sv[id].corr : 0);
let maxCorr = Math.max.apply(null, corrs);
let minCorr = Math.min.apply(null, corrs);
if (maxCorr - minCorr > 30) {
faction.stability = Math.max(0, faction.stability - 1);
}
}
/* Leader below faction average */
let leader = sv[faction.leader];
if (leader && leader.corr < faction.corruption) {
faction.stability = Math.max(0, faction.stability - 2);
}
/* Territory conflict penalty (-1/day while contested) */
if (sv.territoryConflicts) {
sv.territoryConflicts.forEach(function(conflict) {
if (conflict.challengerId === faction.id || conflict.defenderId === faction.id) {
faction.stability = Math.max(0, faction.stability - 1);
}
});
}
/* ── PROTECTION WINDOW ── */
let age = day - (faction.formed || 0);
if (age < FACTION_PROTECTION_WINDOW) {
faction.stability = Math.max(FACTION_PROTECTION_MIN, faction.stability);
}
};
/* ── VECTOR EXCHANGE ─────────────────────────────────────────────────────
Receptive+ factions deepen corruption between members who co-located
today. It NEVER creates a new host — a girl at 0 corruption is not
dragged in by ambient faction pressure. Always reported to the day log.
────────────────────────────────────────────────────────────────────── */
window.factionVectorExchange = function(faction, log) {
if (faction.stance === "neutral" || faction.stance === "uneasy") return;
let sv = State.variables;
let members = faction.members;
let rate = faction.stance === "dominated" ? 2 : 1;
let cap = faction.stance === "dominated" ? 90 : 75;
/* Find co-located pairs */
let locGroups = {};
members.forEach(function(id) {
let c = sv[id];
if (c && c.location) {
if (!locGroups[c.location]) locGroups[c.location] = [];
locGroups[c.location].push(id);
}
});
Object.values(locGroups).forEach(function(group) {
if (group.length < 2) return;
/* Sort by corr desc: higher-corr members spread to lower */
let sorted = group.slice().sort(function(a, b) {
return (sv[b] ? sv[b].corr : 0) - (sv[a] ? sv[a].corr : 0);
});
let donor = sv[sorted[0]];
let receiver = sv[sorted[sorted.length - 1]];
if (!donor || !receiver) return;
if (donor.corr <= receiver.corr) return;
if (receiver.corr >= cap) return;
if (!receiver.infected) return; /* deepen only — never a new host */
var before = receiver.corr;
receiver.corr = Math.min(cap, receiver.corr + rate);
var gained = receiver.corr - before;
if (gained > 0 && log) {
/* Already names each party only when met — but the partial
fallback threw that away wholesale. Reuse the same per-person
string for both visibility levels. */
var deepMsg = '<span style="color:#cc88ff;">🕯 <b>' + window.factionDisplayNameCap(faction) + '</b> — ' +
(donor.met ? donor.name : "a member") + ' deepened ' +
(receiver.met ? '<b>' + receiver.name + '</b>' : 'another member') +
' (+' + gained + ').</span>';
window.factionLog(log, faction, deepMsg, deepMsg);
}
});
};
/* ── CLASH ───────────────────────────────────────────
After deriving home locations for all factions, check if any location
is claimed by more than TERRITORY_MAX_PER_LOC factions.
The newest claimant becomes the challenger.
────────────────────────────────────────────────────────────────────── */
/* =========================================================================
CLASH SYSTEM (full rework)
========================================================================= */
/* ── CAPTIVE HELPERS ── */
/* Returns true if she was actually taken. An unmet girl is never a valid
captive — the captive block names her, shows her portrait and gives her a
morning scene, none of which work for a stranger, and the old
`met = true` line here skipped her real introduction. Callers filter for
met girls already; this is the backstop. */
window.makeCaptive = function(id, days) {
var sv = State.variables;
var c = sv[id];
if (!c) return false;
if (!c.met) return false;
if (c.arrested) return false;
c.captive = true;
c.captiveDays = days || 5;
window.recordInfection(c, "captive", c.location); /* all captives are infected */
if (c.corr === 0) c.corr = 1;
/* No instant bonus on capture. There used to be a flat +5 here, on the
reasoning that an abduction should be worth something before the first
night passed — but processCaptives() runs the same night she is taken
and already applies infectionPower + parasiteLevel. The two stacked, so
her first day was 5 + up to 24 = 29 points, which is most of a tier
before you had done anything with her. The nightly tick alone is the
whole of it now. */
/* A captive is out of circulation — she must leave whatever faction she
belonged to. Previously she stayed on the roster and could even remain
its LEADER, so a girl locked in your mansion went on setting her old
faction's stance with corruption that ignores every cap. */
(sv.factions || []).forEach(function(f) {
if (f.members.indexOf(id) === -1) return;
f.members = f.members.filter(function(m) { return m !== id; });
if (f.leader === id) {
var succ = null, best = -1;
f.members.forEach(function(mid) {
var m = sv[mid];
if (m && !m.captive && m.corr > best) { best = m.corr; succ = mid; }
});
f.leader = succ;
if (succ && sv[succ]) f.name = sv[succ].name + "'s Friends";
}
f.lastStructuralChange = sv.day;
});
return true;
};
window.releaseCaptive = function(id, log) {
var sv = State.variables;
var c = sv[id];
if (!c || !c.captive) return;
c.captive = false;
c.captiveDays = 0;
var label = c.met ? '<b>' + c.name + '</b>' : '<b>someone</b>';
log.push('<span style="color:#aaa">🔓 ' + label + ' was released from captivity.</span>');
/* ── SHE COSTS A SLOT AGAIN ───────────────────────────────────────────
A captive is exempt from the hivemind load while she is held --
getHivemindLoad() excludes her. The day she walks out she counts like
everyone else, so without this, letting a captive go could push you
over the cap through no action of your own, and a faction war that
took several girls could strand you above the limit for days.
Holding someone properly teaches the parasite to hold her at a
distance: +1 permanent capacity, granted ONCE per girl. capBonusGiven
stops a girl taken and released repeatedly from farming it, and the
infected test stops a clean girl who was merely held from paying out.
────────────────────────────────────────────────────────────────── */
if (c.infected && !c.capBonusGiven) {
c.capBonusGiven = true;
sv.hivemindCap = (sv.hivemindCap || 5) + 1;
log.push('<span style="color:#44aaff">🧠 ' + label +
' is yours at a distance now. Hivemind capacity +1 (now ' +
sv.hivemindCap + ').</span>');
}
};
window.processCaptives = function(log) {
var sv = State.variables;
if (!sv.roster) return;
sv.roster.forEach(function(id) {
var c = sv[id];
if (!c || !c.captive) return;
/* Ignores her corruption cap — being held is the one thing that can
push a girl past a threshold you have not bought.
infectionPower + parasiteLevel, which is what the abduction panel
in DayStart has always told the player it would be. The old
Math.min(4, ...) on the level term was undocumented and did nothing
at levels 1-4 anyway, since the level never exceeds 4. */
var gain = (sv.infectionPower || 1) + (sv.parasiteLevel || 1);
c.corr = Math.min(100, c.corr + gain);
c.captiveDays = (c.captiveDays || 1) - 1;
if (c.captiveDays <= 0) window.releaseCaptive(id, log);
});
};
/* ── ENTHRALLED AGENTS ───────────────────────────────────────────────────
Upgrade: factionAutoSpread (T3) — one agent, acts ~30% of nights.
factionAutoSpread2 (T4) — up to two, acts ~50% of nights.
Each night, a member of an ENTHRALLED-or-better faction who is standing
with a girl outside the faction may take her. Nothing happens immediately:
the abduction is PROPOSED and queued for the player to approve at DayStart,
because it costs +10 suspicion each and the player must accept that.
Targets must be UNDER corruption 50. Abduction is a way to force progress on
a girl who is resisting or unreachable; a girl at 50+ is already coming along
on her own and is not worth +10 suspicion.
Approved in DayStart -> makeCaptive(target, 5) + addSuspicion(10).
────────────────────────────────────────────────────────────────────── */
/* =========================================================================
§ 1. CONFIGURATION & AUTOSAVE
========================================================================= */
Config.saves.maxAutoSaves = 1;
Config.saves.isAllowed = function (type) {
if (type === Save.Type.Auto && tags().includes("noautosave")) return false;
return true;
};
/* ── SAVE LABELS ──────────────────────────────────────────────────────────
Every slot used to read the same thing, so a save list was a column of
identical rows and the only way to tell them apart was the timestamp.
Config.saves.descriptions is a function in SugarCube 2.37 — whatever it
returns becomes the slot's label. Build it from the state that actually
distinguishes one save from another:
Day 34 · Friday — Juvenile · 12 girls · Susp 40
$name is not included: it is the same in every save in a given playthrough
and would waste the width. Saves made before this existed keep whatever
label they already have; nothing is rewritten retroactively.
────────────────────────────────────────────────────────────────────── */
Config.saves.descriptions = function (saveType) {
var sv = State.variables;
/* Defensive throughout — this runs during save creation, and a throw here
loses the save. Every field falls back rather than failing. */
var day = (sv.day === 0 || sv.day) ? sv.day : "?";
var wday = sv.weekDay || "";
var lvl = sv.parasiteLevel || 1;
var name = ["", "Hatchling", "Juvenile", "Mature", "Apex"][lvl] || "Hatchling";
var held = 0;
try {
held = (typeof window.getHivemindLoad === "function")
? window.getHivemindLoad()
: (sv.roster || []).filter(function (id) {
var c = sv[id];
return c && c.infected && !c.arrested && !c.captive;
}).length;
} catch (e) { held = 0; }
if (typeof held !== "number" || isNaN(held)) held = 0;
var bits = ["Day " + day + (wday ? " \u00b7 " + wday : "")];
bits.push(name);
bits.push(held + (held === 1 ? " girl" : " girls"));
if ((sv.suspicion || 0) > 0) bits.push("Susp " + sv.suspicion);
if (saveType === Save.Type.Auto) bits.push("auto");
return bits.join(" \u00b7 ");
};
/* ── NIGHT REPORT GROUPING ───────────────────────────────────────────────
The log is built in execution order — passive ticks, vectors, nests,
factions, suspicion, then goals — and every subsystem pushes into the same
flat array. On a busy night that reads as unrelated lines interleaved.
The execution order cannot change; the systems depend on each other. So the
log is sorted at RENDER time instead. Classification keys off the icon and
wording each subsystem already uses, so not one call site had to be
touched — all 83 message templates across nine files stay as they are.
Section order is deliberate: what you gained, then your infrastructure,
then the people you hold, then what it cost you, then what to do next.
────────────────────────────────────────────────────────────────────── */
window.DAYLOG_SECTIONS = [
/* Game over. Always first, never grouped under a heading. */
{ id: "critical", label: "", colour: "#ff2222",
test: function (t) { return /SUSPICION CRITICAL|COVER IS BLOWN/.test(t); } },
/* Corruption gained, vectors spreading, passive upgrade effects. */
{ id: "spread", label: "Corruption & spread", colour: "#bd59ff",
test: function (t) {
return /reached a new stage|\(Vector\) secretly infected|focused on <b>|influenced <b>|Territorial Infection|Location Control|Whisper Network|Multiple Vectors/.test(t);
} },
/* Anything the police did — checked BEFORE nests, because a raid is a
security event that happens to mention a nest. */
{ id: "security", label: "Security", colour: "#ff8844",
test: function (t) {
return /🚔|🔍|▲ High-level nest|acted strangely|✓ The detective|witnessed!|discovered and destroyed|partially detected/.test(t);
} },
{ id: "nests", label: "Nests", colour: "#44cc88",
test: function (t) { return /Nest at|Nexus at|nest at|breeding nest|spawned a Nest/.test(t); } },
{ id: "factions", label: "Factions", colour: "#44aaff",
test: function (t) {
return /\u2014 Factions \u2014|▸|★|⚔|⚡|🏴|🤝|✂|💀|📋|📍|🕵|🗡|🎉|🕷|🏛|SPLIT:|absorbed into|joined <b>|Captives:|⬅/.test(t);
} },
/* The Lab, arrests and releases. */
{ id: "captives", label: "The Lab & captives", colour: "#cc88ff",
test: function (t) { return /⚗|🔓|The Lab/.test(t); } },
/* Objectives, and territory falling to you — a dominated location is
either a goal reward or a faction leader hitting 75, so it belongs with
the things you achieved rather than under "Also". */
{ id: "goals", label: "Objectives & territory", colour: "#ffcc44",
test: function (t) {
return /🎯|\u2726 New objective|is now dominated|falls under the parasite/.test(t);
} },
/* Anything unclassified still shows, rather than being swallowed. */
{ id: "other", label: "Also", colour: "#7a7a8a",
test: function () { return true; } }
];
/* Returns [{ id, label, colour, lines: [...] }] with empty sections dropped.
Order within a section is preserved exactly as the night produced it. */
window.groupDayLog = function (log) {
var defs = window.DAYLOG_SECTIONS;
var buckets = {};
defs.forEach(function (d) { buckets[d.id] = []; });
(log || []).forEach(function (line) {
var txt = String(line);
for (var i = 0; i < defs.length; i++) {
if (defs[i].test(txt)) { buckets[defs[i].id].push(line); break; }
}
});
return defs
.filter(function (d) { return buckets[d.id].length > 0; })
.map(function (d) {
return { id: d.id, label: d.label, colour: d.colour, lines: buckets[d.id] };
});
};
/* =========================================================================
§ 2. IMAGE HELPERS
========================================================================= */
window.getCorrSuffix = function(corr) {
if (corr >= 100) return "Corr4";
if (corr >= 75) return "Corr3";
if (corr >= 50) return "Corr2";
if (corr >= 25) return "Corr1";
return "Normal";
};
window.isPlayer = function(charName) {
if (!charName) return false;
var playerName = State.variables.name || "";
return charName === playerName ||
charName.toLowerCase() === "player" ||
charName === "$name";
};
/* Always resolves folder name from canonical .name field on the character
object — never from the raw argument. Linux hosting is case-sensitive. */
window.getCharFolderName = function(charName) {
if (!charName) return charName;
var charVar = State.variables[charName.toLowerCase()];
return (charVar && charVar.name) ? charVar.name : charName;
};
window.getPortraitPath = function(charName) {
if (!charName) return "";
if (window.isPlayer(charName)) return "img/Characters/Player/Portrait.jpg";
var charVar = State.variables[charName.toLowerCase()];
var folder = window.getCharFolderName(charName);
var filename = (charVar && charVar.corr >= 75) ? "PortraitCorr.jpg" : "Portrait.jpg";
return "img/Characters/" + folder + "/" + filename;
};
window.getEventImagePath = function(charName) {
if (!charName) return "";
if (window.isPlayer(charName)) return "img/Characters/Player/Portrait.jpg";
var charVar = State.variables[charName.toLowerCase()];
var folder = window.getCharFolderName(charName);
var suffix = charVar ? window.getCorrSuffix(charVar.corr) : "Normal";
return "img/Characters/" + folder + "/" + suffix + ".jpg";
};
window.getImagePath = function(charName) {
return window.getEventImagePath(charName);
};
/* Scene-tier image. Used by location scenes so every girl in the scene is
shown at the SCENE's tier rather than her own corruption — the scene text
is written for one tier, so the pictures must agree with it.
Tier 1 -> Normal.jpg Tier 2 -> Corr1.jpg
Tier 3 -> Corr3.jpg Tier 4 -> Corr4.jpg */
window.TIER_IMAGE = { 1: "Normal", 2: "Corr1", 3: "Corr3", 4: "Corr4" };
window.getTierImagePath = function(charName, tier) {
if (!charName) return "";
if (window.isPlayer(charName)) return "img/Characters/Player/Portrait.jpg";
var suffix = window.TIER_IMAGE[tier];
if (!suffix) return window.getEventImagePath(charName); /* unknown tier */
return "img/Characters/" + window.getCharFolderName(charName) + "/" + suffix + ".jpg";
};
/* =========================================================================
§ 3. SPEECH & THOUGHT MACROS
========================================================================= */
Macro.add('speech', {
tags: null,
handler: function () {
var playerName = State.variables.name || "";
var id = this.args[0];
var name = this.args.length > 1 ? this.args[1] : null;
if (id === "player" || id === "$name" || id === playerName) {
id = "player";
name = name || playerName;
} else {
var charObj = State.variables[id] || State.variables[id.toLowerCase()];
name = name || (charObj && charObj.name ? charObj.name : id);
}
/* The name and the line are wrapped in their own elements now. The
old markup put a bare <hr> across the whole card, which drew a rule
straight through the space beside the avatar and forced the
min-height that made every one-line reply the size of a paragraph.
Styling lives in the stylesheet — see .speech / .avatar. */
var imageURL = window.getPortraitPath(id);
var output = '<div class="speech">';
output += '<span class="avatar" style="background-image: url(\'' + imageURL + '\');"></span>';
output += '<span class="speech-name">' + name + '</span>';
output += '<span class="speech-body">' + this.payload[0].contents + '</span>';
output += '</div>';
$(this.output).wiki(output);
}
});
Macro.add('thought', {
tags: null,
handler: function () {
var playerName = State.variables.name || "";
var id = (this.args.length > 0) ? this.args[0] : null;
var name = null;
if (id) {
if (id === "player" || id === "$name" || id === playerName) {
id = "player";
name = this.args.length > 1 ? this.args[1] : playerName;
} else if (this.args.length > 1) {
name = this.args[1];
} else {
name = id.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
}
}
var output = '<div class="thought">';
if (id) {
var imageURL = window.getPortraitPath(id);
output += '<span class="avatar" style="background-image: url(\'' + imageURL + '\');"></span>';
}
if (name) output += '<span class="speech-name">' + name + ' thinks:</span>';
output += '<span class="speech-body">' + this.payload[0].contents + '</span>';
output += '</div>';
$(this.output).wiki(output);
}
});
/* =========================================================================
§ 4. CHARACTER POPUP
========================================================================= */
window.showCharPopup = function(charId) {
var charObj = State.variables[charId];
if (!charObj) return;
Dialog.setup("Character Bio", "character-popup");
var portraitImg = window.getPortraitPath(charObj.name);
var corrCap = (typeof window.getCorrCap === "function") ? window.getCorrCap() : 25;
var statusList = [];
if (charObj.infected) statusList.push("<span style='color:#bd59ff'>☣ Infected</span>");
if (charObj.breed) statusList.push("<span style='color:#ff5959'>♥ Bred</span>");
if (charObj.arrested) statusList.push("<span style='color:#ff2222'>🚔 Detained</span>");
if (statusList.length === 0) statusList.push("<span style='color:#aaa'>Healthy</span>");
var corrText = "Unaware";
if (charObj.corr >= 100) corrText = "Vector";
else if (charObj.corr >= 75) corrText = "Devoted";
else if (charObj.corr >= 50) corrText = "Receptive";
else if (charObj.corr >= 25) corrText = "Curious";
var atCap = charObj.infected && charObj.corr >= corrCap && charObj.corr < 100;
var capLabel = atCap
? `<span style="color:#bd59ff; font-size:0.8em; margin-left:8px;">⬆ At cap (${corrCap}) — break to progress</span>`
: "";
/* Infection register — where, when and how she was taken. */
var rec = window.getInfectionRecord ? window.getInfectionRecord(charObj) : null;
/* Named occasions read as one sentence — "at the Harem Mansion party on
day 110". Everything else keeps place-then-method, which is the right
shape for "Cafeteria · Direct contact". */
var infLine = "";
if (rec && rec.event) {
infLine = `<div style="color:#8a6a9a; font-size:0.78em; margin:-4px 0 10px;">☣ Taken at <b style="color:#bd59ff;">${rec.event}</b> on <b style="color:#bd59ff;">day ${rec.day}</b></div>`;
} else if (rec) {
infLine = `<div style="color:#8a6a9a; font-size:0.78em; margin:-4px 0 10px;">☣ Taken on <b style="color:#bd59ff;">day ${rec.day}</b> at <b style="color:#bd59ff;">${rec.where}</b> · ${rec.how}</div>`;
}
var traitLabel = "";
if (charObj.trait === "authority") traitLabel = "<span style='color:#ffaa22'>⚖ Authority</span>";
if (charObj.trait === "influential") traitLabel = "<span style='color:#44aaff'>◈ Influential</span>";
if (charObj.trait === "flashpoint") traitLabel = "<span style='color:#ff4444'>⚡ Flashpoint</span>";
var content = `
<div class="char-popup-container">
<div class="char-popup-portrait" style="background-image: url('${portraitImg}');"></div>
<div class="char-popup-details">
<div class="char-header-row">
<div class="char-name-large">${charObj.name}</div>
<div class="char-group-tag">${window.getGroupLabel ? window.getGroupLabel(charObj.group) : charObj.group}</div>
</div>
${charObj.actress ? `<div style="color:#888; font-size:0.78em; font-style:italic; margin-bottom:10px; letter-spacing:0.04em;">portrayed by ${charObj.actress}</div>` : ''}
<div class="status-row">Status: <strong>${statusList.join(" | ")}</strong>
${traitLabel ? " | " + traitLabel : ""}
</div>
${infLine}
<div style="color:#ddd; margin-bottom:15px; font-size:0.9em;">${charObj.description}</div>
<div class="popup-bar-wrap">
<div class="popup-bar-fill" style="width: ${charObj.corr}%;"></div>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.8em; margin-top:4px;">
<span>Stage: <span style="color:#cc88ff">${corrText}</span>${capLabel}</span>
<span>Corruption: ${charObj.corr}%</span>
</div>
</div>
</div>`;
Dialog.wiki(content);
Dialog.open();
};
/* =========================================================================
§ 5. KEYBOARD SHORTCUTS
========================================================================= */
$(document).on('keyup', function(event) {
if ($(event.target).is("input, textarea, select")) return;
var key = event.key;
if (key === 'f' || key === 'F') { Engine.play('Factions'); return; }
if (key === 'g' || key === 'G') { Engine.play('Goals'); return; }
if (key === 'c' || key === 'C') { Engine.play('Characters'); return; }
if (key === 'u' || key === 'U') { Engine.play('Upgrades'); return; }
if (key === '?' || key === '/') { Engine.play('Shortcuts'); return; }
if (key === 'p' || key === 'P') {
State.variables.parasite += 1;
State.variables.dayLog = [State.variables.name + " produced a parasite via shortcut."];
Engine.play("DayEnd");
return;
}
if (key === 'q' || key === 'Q') {
var navKeywords = ["day", "wake", "end", "sleep", "finish", "continue", "return"];
var $match = $('#passages button, #passages a').filter(':visible').filter(function() {
var btnText = $(this).text().toLowerCase();
return navKeywords.some(word => btnText.includes(word));
}).first();
if ($match.length) { $match[0].click(); }
return;
}
if (key === '+' || key === '=') { Engine.forward(); return; }
if (key === '-' || key === '_') { Engine.backward(); return; }
var num = parseInt(key, 10);
if (isNaN(num) || num < 1 || num > 9) return;
var card = $('[data-girl-key="' + num + '"]');
if (card.length) {
var approachBtn = card.find('button').filter(function() { return $(this).text().indexOf('Approach') !== -1; });
var interactBtn = card.find('button').filter(function() { return $(this).text().indexOf('Interact') !== -1; });
var infectBtn = card.find('button').filter(function() { return $(this).text().indexOf('Infect') !== -1; });
var anyBtn = card.find('button').first();
var target = approachBtn.length ? approachBtn.first()
: interactBtn.length ? interactBtn.first()
: infectBtn.length ? infectBtn.first()
: anyBtn;
if (target && target.length) { target[0].click(); return; }
}
var str = String(num);
var match = $('button, a').filter(':visible').filter(function() {
return $(this).text().indexOf(str) !== -1;
}).first();
if (match.length) { match[0].click(); }
});
/* ── AUTO-NUMBER GIRL CARDS ── */
$(document).on(':passagerender', function() {
setTimeout(function() {
$('[data-girl-key]').removeAttr('data-girl-key');
var cards = $('[data-girl-card]');
cards.each(function(i) {
if (i < 9) $(this).attr('data-girl-key', i + 1);
});
}, 50);
});
/* =========================================================================
§ CAN THIS GIRL BE INFECTED?
Central guard. A girl the player has never met cannot be infected
unless the "Blind Reach" (infectUnmet) upgrade is owned.
Every automated infection path must call this.
========================================================================= */
window.getHivemindLoad = function() {
var sv = State.variables;
if (!sv.roster) return 0;
/* Two kinds of infected girl cost no slot:
A CAPTIVE is in the house, worked on directly rather than run
remotely. She starts counting again the day she is released, which is
why releaseCaptive() grants +1 permanent capacity — the slot she
reoccupies is one you have already paid for.
The ARRESTED are out of reach either way.
A VECTOR at corr 100 COUNTS LIKE EVERYONE ELSE. She used to be exempt,
on the reasoning that she is one with the parasite and costs it
nothing to hold. That made the deepest hold in the game a free one and
turned the cap into a formality: five girls at 99 filled a cap of five,
the same five at 100 read as zero. Reaching 100 is still worth doing —
she spreads on her own overnight, the Lab cannot strip her, and arrest
finds nothing in her — but it no longer refunds the slot. */
return sv.roster.filter(function(id) {
var c = sv[id];
if (!c || !c.infected) return false;
if (c.arrested || c.captive) return false;
return true;
}).length;
};
window.hivemindFull = function() {
var sv = State.variables;
return window.getHivemindLoad() >= (sv.hivemindCap || 5);
};
/* canInfect(c) — may this girl be NEWLY infected right now?
Checks, in order: exists, not detained, hivemind has room,
and she is met (or Blind Reach is owned).
Pass true as 2nd arg to skip the capacity check — used by paths
that only tick corruption on someone already infected. */
/* ── AUTOMATIC INFECTION: THE ONE GATE ────────────────────────────────────
$settings.autoInfect, ON by default.
Read through this function everywhere rather than testing the setting
inline, so every site agrees and a future caller cannot miss one.
WHAT IT BLOCKS -- everything that infects a girl with no player action:
* a vector seeding a random girl overnight
* nest drift catching a passer-by
* every nest effect that infects (spread, intimate, socialHub, transient)
* Location Control: Social Hub, and Territorial Infection
* a bred girl spawning a NEW spreading nest
WHAT IT DOES NOT BLOCK -- anything the player chose:
* the Infect button
* taking a captive
* a party or activity the player attended
* an ESTABLISHED nest the player planted: it keeps spreading. The setting
stops new automatic nests appearing, not the ones already standing.
* deepening corruption on a girl who is ALREADY infected -- the setting
is about who gets taken, not how far.
────────────────────────────────────────────────────────────────────── */
window.autoInfectOn = function () {
var s = State.variables.settings;
/* Absent means on: a save made before this setting existed must behave
exactly as it did. */
return !s || s.autoInfect !== false;
};
window.canInfect = function(c, ignoreCap) {
if (!c) return false;
if (c.arrested) return false;
if (!ignoreCap && !c.infected && window.hivemindFull()) return false;
if (c.met) return true;
var ups = State.variables.upgrades || {};
return !!ups.infectUnmet;
};
/* =========================================================================
§ INFECTION REGISTER
Records where, when and how each girl was first infected. Write-once:
re-infecting an already-recorded girl never overwrites the original entry,
so the record is always the moment she was actually taken.
Every site that sets `infected = true` calls this instead. If one is ever
missed the girl simply has no record — nothing breaks.
========================================================================= */
window.INFECT_METHODS = {
direct: "Direct contact",
exposure: "Nest exposure",
vector: "Vector network",
nest: "Nest bloom",
faction: "Faction spread",
captive: "Taken captive",
upgrade: "Passive spread",
party: "At a gathering",
cheat: "Debug"
};
/* Mark a girl infected AND log it. Returns true if this was a new infection.
`event` is an optional human-readable name for the specific occasion — "the
Harem Mansion party", "Marie's Friends' party", "Chanel's Class lecture".
When present it replaces the generic method label, because "At a gathering"
next to a location told the player nothing about which gathering. */
window.recordInfection = function (id, method, location, event) {
var sv = State.variables;
var c = typeof id === "string" ? sv[id] : id;
if (!c) return false;
var wasClean = !c.infected;
c.infected = true;
/* Write-once — the first taking is the one that counts. */
if (!c.infectedOn) {
c.infectedOn = sv.day || 0;
c.infectedWhere = location || c.location || sv.currentLocation || "Unknown";
c.infectedHow = method || "unknown";
if (event) c.infectedEvent = event;
}
return wasClean;
};
/* "Day 12 · Cafeteria · Direct contact" — for character sheets.
Returns `event` when the infection happened at a named occasion, so the
popup can write "at Marie's Friends' party on day 12" rather than naming a
room and then vaguely calling it a gathering. */
window.getInfectionRecord = function (id) {
var c = typeof id === "string" ? State.variables[id] : id;
if (!c || !c.infected) return null;
if (!c.infectedOn && c.infectedOn !== 0) {
return { day: null, where: "Unknown", how: "Unknown", event: null,
text: "Infected before records were kept" };
}
var how = window.INFECT_METHODS[c.infectedHow] || c.infectedHow || "Unknown";
var ev = c.infectedEvent || null;
return {
day: c.infectedOn,
where: c.infectedWhere || "Unknown",
how: how,
event: ev,
text: ev
? "Day " + c.infectedOn + " · " + ev
: "Day " + c.infectedOn + " · " + (c.infectedWhere || "Unknown") + " · " + how
};
};<<back>>
<h1 style="margin-bottom:6px;">📅 Characters Agenda</h1>
<div style="color:#666; font-size:0.82em; margin-bottom:20px;">Day $day · $weekDay — Current locations and weekly schedule</div>
<<nobr>>
<<for _gi to 0; _gi lt $groups.length; _gi++>>
<<set _groupName = $groups[_gi].name>>
<<set _members = $groups[_gi].members>>
/* Only show groups that have at least one met character */
<<set _anyMet = _members.some(id => State.variables[id] && State.variables[id].met)>>
<<if _anyMet>>
<div style="margin-bottom:28px;">
<div style="font-size:0.7em; font-weight:bold; text-transform:uppercase; letter-spacing:0.12em; color:#9c27b0; border-bottom:1px solid #2a0040; padding-bottom:4px; margin-bottom:10px;">
<<print _groupName>>
</div>
<div style="display:grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap:8px;">
<<for _id range _members>>
<<set _c = State.variables[_id]>>
<<if _c and _c.met>>
<<capture _id>>
<div style="background:#0d0d1a; border:1px solid #222; border-radius:6px; padding:10px 12px; display:flex; gap:10px; align-items:flex-start;">
/* Portrait */
<img @src="window.getPortraitPath(_c.name)"
style="width:44px; height:66px; border-radius:50%; object-fit:cover; object-position:top; border:2px solid #9c27b0; flex-shrink:0;">
<div style="flex:1; min-width:0;">
/* Name + status */
<div style="display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-bottom:4px;">
<span style="font-weight:bold; color:#ccc; font-size:0.9em;"><<print _c.name>></span>
<<if _c.arrested>>
<span style="font-size:0.7em; color:#ff2222; background:#1a0000; border:1px solid #ff2222; border-radius:3px; padding:1px 5px;">🚔 Detained</span>
<<elseif _c.breed>>
<span style="font-size:0.7em; color:#ff5959; background:#1a0010; border:1px solid #ff5959; border-radius:3px; padding:1px 5px;">♥ Bred</span>
<<elseif _c.infected>>
<span style="font-size:0.7em; color:#bd59ff; background:#0d0018; border:1px solid #bd59ff; border-radius:3px; padding:1px 5px;">☣ Infected</span>
<</if>>
</div>
/* Current location */
<div style="font-size:0.78em; margin-bottom:5px;">
<span style="color:#555;">Now: </span>
<<if _c.arrested>>
<span style="color:#ff4444;">The Lab</span>
<<else>>
<span style="color:#bd59ff;"><<print _c.location || "Unknown">></span>
<</if>>
</div>
/* Corruption bar */
<<if _c.corr > 0>>
<div style="margin-bottom:5px;">
<div style="background:#1a1a1a; border-radius:3px; height:4px; width:100%;">
<div @style="'width:' + _c.corr + '%; height:100%; border-radius:3px; background:#9c27b0;'"></div>
</div>
<div style="color:#555; font-size:0.7em; margin-top:1px;">Corruption: <<print _c.corr>>%</div>
</div>
<</if>>
/* Schedule */
<<if _c.schedule>>
<div style="font-size:0.72em; color:#444; margin-top:3px;">
<<if _c.schedule.weekday and _c.schedule.weekday.length > 0>>
<div><span style="color:#555;">Weekday: </span><span style="color:#888;"><<print _c.schedule.weekday.join(", ")>></span></div>
<</if>>
<<if _c.schedule.weekend and _c.schedule.weekend.length > 0>>
<div><span style="color:#555;">Weekend: </span><span style="color:#888;"><<print _c.schedule.weekend.join(", ")>></span></div>
<</if>>
</div>
<</if>>
</div>
</div>
<</capture>>
<</if>>
<</for>>
</div>
</div>
<</if>>
<</for>>
<</nobr>><<back>>
<h1 style="margin-bottom:6px;">🗺 Location Agenda</h1>
<div style="color:#666; font-size:0.82em; margin-bottom:20px;">Day $day · $weekDay — Nest status, pillars and control</div>
<<nobr>>
<<set _traitLabels = {
"intimate": { label: "Intimate", color: "#44ff88" },
"socialHub": { label: "Social Hub", color: "#88aaff" },
"academic": { label: "Academic", color: "#ffcc44" },
"outdoor": { label: "Outdoor", color: "#66cc66" },
"transient": { label: "Transient", color: "#aaaaaa" },
"critical": { label: "Critical", color: "#ff4444" }
}>>
<<set _lastSection = "">>
<<for _loc range $locations>>
<<if not _loc.unlocked>><<continue>><</if>>
<<if _loc.noGoal>><<continue>><</if>> /* Harem Mansion — not a target */
<<if _loc.section isnot _lastSection>>
<<set _lastSection = _loc.section>>
<div style="font-size:0.7em; font-weight:bold; text-transform:uppercase; letter-spacing:0.12em; color:#9c27b0; border-bottom:1px solid #2a0040; padding-bottom:4px; margin:24px 0 10px;">
<<print _loc.section>>
</div>
<</if>>
<<capture _loc>>
/* ── Nest state ── */
<<set _nest = $nests[_loc.name]>>
<<set _hasNest = _nest && _nest.level > 0>>
<<set _nestLevel = _hasNest ? _nest.level : 0>>
<<set _nestDays = _hasNest ? _nest.days : 0>>
<<set _nestType = _hasNest ? (_nest.type || "spreading") : "">>
/* ── Pillar state ── */
<<set _pillars = _loc.pillars || []>>
<<set _alwaysUnsafe = _loc.alwaysUnsafe || false>>
<<set _pillarsMet = []>>
<<set _pillarsQual = 0>>
<<for _pid range _pillars>>
<<set _pc = State.variables[_pid]>>
<<if _pc and _pc.met>>
<<run _pillarsMet.push(_pid)>>
<<if _nestType is "breeding">>
<<if _pc.infected>><<set _pillarsQual += 1>><</if>>
<<else>>
<<if _pc.corr >= 25>><<set _pillarsQual += 1>><</if>>
<</if>>
<</if>>
<</for>>
/* ── Safety calculation ── */
<<set _isSafe = false>>
<<if _alwaysUnsafe>>
<<set _isSafe = false>>
<<elseif _pillars.length is 0>>
<<set _isSafe = true>>
<<elseif _loc.trait is "critical">>
<<set _isSafe = _pillarsQual is _pillars.length>>
<<elseif _pillars.length is 1>>
<<set _isSafe = _pillarsQual is 1>>
<<else>>
<<set _isSafe = (_pillarsQual / _pillars.length) >= 0.7>>
<</if>>
/* ── Dominated ── */
<<set _isDominated = $goalBonuses && $goalBonuses.corruptedLocations && $goalBonuses.corruptedLocations.includes(_loc.name)>>
/* ── Trait label ── */
<<set _traitData = _traitLabels[_loc.trait] || { label: _loc.trait, color: "#888" }>>
<div style="background:#0d0d1a; border:1px solid <<print _isDominated ? '#9c27b0' : '#1a1a1a'>>; border-radius:6px; padding:10px 14px; margin-bottom:6px; display:flex; gap:12px; align-items:flex-start;">
/* ── LEFT: name + badges ── */
<div style="flex:1; min-width:0;">
<div style="display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-bottom:6px;">
<span style="font-weight:bold; color:#ccc; font-size:0.9em;"><<print _loc.navLabel>></span>
/* Trait badge */
<span style="font-size:0.68em; color:<<print _traitData.color>>; background:#0a0a0a; border:1px solid <<print _traitData.color>>; border-radius:3px; padding:1px 5px;">
<<print _traitData.label>>
</span>
/* Dominated badge */
<<if _isDominated>>
<span style="font-size:0.68em; color:#bd59ff; background:#0d0018; border:1px solid #bd59ff; border-radius:3px; padding:1px 5px;">☣ Dominated</span>
<</if>>
/* Safety badge */
<<if _alwaysUnsafe>>
<span style="font-size:0.68em; color:#ff4444; background:#1a0000; border:1px solid #ff4444; border-radius:3px; padding:1px 5px;">⛔ Always Exposed</span>
<<elseif _pillars.length is 0>>
<span style="font-size:0.68em; color:#44ff88; background:#001a08; border:1px solid #44ff88; border-radius:3px; padding:1px 5px;">✓ No Pillars</span>
<<elseif _isSafe>>
<span style="font-size:0.68em; color:#44ff88; background:#001a08; border:1px solid #44ff88; border-radius:3px; padding:1px 5px;">✓ Safe</span>
<<else>>
<span style="font-size:0.68em; color:#ff8844; background:#1a0800; border:1px solid #ff8844; border-radius:3px; padding:1px 5px;">⚠ Exposed</span>
<</if>>
</div>
/* ── Pillars row ── */
<<if _pillars.length > 0>>
<div style="font-size:0.75em; color:#555; margin-bottom:5px;">
<span style="color:#444; margin-right:4px;">Pillars:</span>
<<for _pid range _pillars>>
<<set _pc = State.variables[_pid]>>
<<if _pc>>
<<capture _pid>>
<<set _pillarMet = _pc.met>>
<<set _pillarQual = (_nestType is "breeding") ? _pc.infected : (_pc.corr >= 25)>>
<span style="
color: <<if not _pillarMet>>
#333
<<elseif _pillarQual>>
#44ff88
<<else>>
#ff8844
<</if>>;
margin-right:8px;">
<<if _pillarMet>>
<<print _pc.name>>
<<if _pillarQual>> ✓<<else>> ✗<</if>>
<<else>>
???
<</if>>
</span>
<</capture>>
<</if>>
<</for>>
<<if _pillars.length > 1>>
<span style="color:#333; font-size:0.9em;">
(<<print _pillarsQual>>/<<print _pillars.length>> qualified)
</span>
<</if>>
</div>
<</if>>
/* ── Nest row ── */
<<if _hasNest>>
<div style="font-size:0.75em;">
<span style="color:#555;">Nest: </span>
<span style="color:#bd59ff;">
☣ L<<print _nestLevel>>
<<if _nestType is "breeding">> [Breeding]<<else>> [Spreading]<</if>>
</span>
<span style="color:#444; margin-left:6px;"><<print _nestDays>> day<<if _nestDays isnot 1>>s<</if>> remaining</span>
<<if not _isSafe and not _alwaysUnsafe>>
<span style="color:#ff4444; margin-left:6px;">⚠ High detection risk</span>
<</if>>
</div>
<<else>>
<div style="font-size:0.75em; color:#333;">No nest</div>
<</if>>
</div>
</div>
<</capture>>
<</for>>
<</nobr>>[[← Back|TownHub]]
<<nobr>>
<div id="upg-root">
<style>
/* Scoped to this page. The story column is 96% of the viewport, so on a wide
monitor every upgrade row stretched the full width and left its button
stranded far to the right of the name it belonged to — the eye had to
travel the whole line to pair them up.
Two fixes: cap the column at a readable width, and put the price and the
button in a fixed-width panel with its own background and a divider, so
each row reads as one object rather than text and a distant button. */
#upg-root { max-width: 1080px; margin: 0 auto; }
/* Upgrade card ------------------------------------------------- */
#upg-root .upg-row {
display: flex;
align-items: stretch;
gap: 0;
border-radius: 8px;
overflow: hidden;
margin-bottom: 7px;
}
#upg-root .upg-body {
flex: 1;
min-width: 0;
padding: 11px 14px;
}
#upg-root .upg-name {
font-size: 0.95em;
font-weight: bold;
line-height: 1.3;
}
#upg-root .upg-desc {
font-size: 0.82em;
color: #666;
margin-top: 3px;
line-height: 1.5;
max-width: 62ch; /* keeps the description from running to the button */
}
/* The action panel. Fixed width and visually separated, so the button always
sits in the same column no matter how long the name or description is. */
#upg-root .upg-act {
flex: 0 0 132px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 3px;
padding: 10px 8px;
border-left: 1px solid #222;
background: rgba(0,0,0,0.28);
text-align: center;
}
#upg-root .upg-act button {
width: 100% !important;
margin: 0 !important;
padding: 6px 4px !important;
font-size: 0.85em !important;
white-space: nowrap;
}
#upg-root .upg-cost { font-size: 0.78em; color: #777; }
#upg-root .upg-locked { font-size: 0.82em; color: #444; line-height: 1.35; }
@media (max-width: 720px) {
#upg-root .upg-row { flex-direction: column; }
#upg-root .upg-act { flex: 1 1 auto; border-left: none; border-top: 1px solid #222; }
#upg-root .upg-desc { max-width: none; }
}
</style>
/* Mirror of window.PARASITE_LEVEL_CAPS in JS-Upgrades. Keep the two in step. */
<<set _levelCaps = [
null,
{ nestCap: 5, hivemind: 10, infPower: 5, hivemindStep: 1 },
{ nestCap: 7, hivemind: 25, infPower: 10, hivemindStep: 2 },
{ nestCap: 10, hivemind: 50, infPower: 15, hivemindStep: 5 },
{ nestCap: 999, hivemind: 999, infPower: 999, hivemindStep: 10 }
]>>
<<set _lvl = $parasiteLevel || 1>>
<<set _caps = _levelCaps[_lvl]>>
<<set _evoReqs = [
null,
null,
{ cost: 10, label: "3 girls at Corr 25", met: $roster.filter(id => State.variables[id] && State.variables[id].corr >= 25).length >= 3 },
{ cost: 25, label: "1 Authority figure at Corr 50", met: $roster.some(id => { var c = State.variables[id]; return c && c.infected && c.trait === "authority" && c.corr >= 50; }) },
{ cost: 50, label: "5 locations dominated", met: ($goalBonuses.corruptedLocations || []).length >= 5 }
]>>
<<set _lvlNames = [null, "Hatchling", "Juvenile", "Mature", "Apex"]>>
<<set _lvlColors = [null, "#88aaff", "#44cc88", "#ffaa44", "#ff5555"]>>
/* ── HEADER ── */
<div style="text-align:center; padding:20px 0 16px;">
<div style="font-size:0.8em; text-transform:uppercase; letter-spacing:0.15em; color:#666; margin-bottom:8px;">Parasite Evolution</div>
<div style="font-size:2.4em; font-weight:bold; color:<<print _lvlColors[_lvl]>>;"><<print _lvlNames[_lvl]>></div>
<div style="font-size:1em; color:#888; margin-top:4px;">Level <<print _lvl>> of 4</div>
<div style="margin-top:12px; font-size:1.1em; color:#bd59ff; font-weight:bold;">
☣ <<print $parasite>> parasites available
</div>
</div>
/* ── LEVEL TRACK ── */
<div style="display:flex; align-items:center; margin:0 0 24px; padding:0 8px;">
<<for _li to 1; _li lte 4; _li++>>
<div style="flex:1; text-align:center;">
<div style="width:36px; height:36px; border-radius:50%; margin:0 auto; display:flex; align-items:center; justify-content:center; font-weight:bold; font-size:1em;
background:<<if _li lt _lvl>>#1a0030<<elseif _li is _lvl>><<print _lvlColors[_li]>><<else>>#111<</if>>;
border:2px solid <<if _li lte _lvl>><<print _lvlColors[_li]>><<else>>#333<</if>>;
color:<<if _li lte _lvl>>#fff<<else>>#444<</if>>;">
<<if _li lt _lvl>>✓<<else>><<print _li>><</if>>
</div>
<div style="font-size:0.75em; margin-top:5px; color:<<if _li lte _lvl>><<print _lvlColors[_li]>><<else>>#444<</if>>;">
<<print _lvlNames[_li]>>
</div>
</div>
<<if _li lt 4>>
<div style="height:2px; flex:1; background:<<if _li lt _lvl>><<print _lvlColors[_li]>><<else>>#222<</if>>; margin-bottom:22px;"></div>
<</if>>
<</for>>
</div>
/* ── CORE STATS ── */
<div style="background:#111; border:1px solid #2a0050; border-radius:10px; padding:16px; margin-bottom:24px;">
<div style="font-size:0.8em; text-transform:uppercase; letter-spacing:0.1em; color:#6a0dad; margin-bottom:14px; font-weight:bold;">Core Stats</div>
<div style="display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; margin-bottom:16px;">
<<set _nestCurrent = $nestCap || 2>>
<<set _nestCost = 3 + (_nestCurrent * 2)>>
<div style="background:#1a1a2a; border-radius:8px; padding:10px; text-align:center;">
<div style="font-size:0.8em; color:#888; margin-bottom:4px;">🪹 Nest Cap</div>
<div style="font-size:1.4em; font-weight:bold; color:#bd59ff;"><<print _nestCurrent>></div>
<div style="font-size:0.75em; color:#555; margin-top:2px;">max <<print _caps.nestCap>> this level</div>
</div>
<<set _hiveCurrent = $hivemindCap || 5>>
<<set _hiveStep = _caps.hivemindStep>>
<<set _hiveCost = 2 + (Math.floor(_hiveCurrent / 5))>>
<div style="background:#1a1a2a; border-radius:8px; padding:10px; text-align:center;">
<div style="font-size:0.8em; color:#888; margin-bottom:4px;">🧠 Hivemind</div>
<div style="font-size:1.4em; font-weight:bold; color:#bd59ff;"><<print _hiveCurrent>></div>
<div style="font-size:0.75em; color:#555; margin-top:2px;">max <<print _caps.hivemind>> this level</div>
</div>
<<set _infCurrent = $infectionPower || 1>>
<<set _infCost = 2 + (_infCurrent * 2)>>
<div style="background:#1a1a2a; border-radius:8px; padding:10px; text-align:center;">
<div style="font-size:0.8em; color:#888; margin-bottom:4px;">☣ Inf. Power</div>
<div style="font-size:1.4em; font-weight:bold; color:#bd59ff;"><<print _infCurrent>></div>
<div style="font-size:0.75em; color:#555; margin-top:2px;">max <<print _caps.infPower>> this level</div>
</div>
</div>
/* Repeatable upgrade rows */
<div style="display:flex; flex-direction:column; gap:8px;">
<div class="upg-row" style="background:#1a1a2a;">
<div class="upg-body">
<div class="upg-name" style="color:#ddd;">🪹 Nest Cap +1</div>
<div class="upg-desc"><<print _nestCurrent>> → <b style="color:#999;"><<print _nestCurrent + 1>></b> · cap <<print _caps.nestCap>> at this level</div>
</div>
<div class="upg-act">
<<if _nestCurrent >= _caps.nestCap>>
<span class="upg-locked">Evolve<br>to raise</span>
<<elseif $parasite >= _nestCost>>
<<button "Buy">><<run window.buyUpgrade("nestCap")>><<goto "Upgrades">><</button>>
<span class="upg-cost">☣ <<print _nestCost>></span>
<<else>>
<span class="upg-locked">☣ <<print _nestCost>><br><span style="color:#333;">need <<print _nestCost - $parasite>> more</span></span>
<</if>>
</div>
</div>
<div class="upg-row" style="background:#1a1a2a;">
<div class="upg-body">
<div class="upg-name" style="color:#ddd;">🧠 Hivemind +<<print _hiveStep>></div>
<div class="upg-desc"><<print _hiveCurrent>> → <b style="color:#999;"><<print _hiveCurrent + _hiveStep>></b> · cap <<print _caps.hivemind>> at this level</div>
</div>
<div class="upg-act">
<<if _hiveCurrent >= _caps.hivemind>>
<span class="upg-locked">Evolve<br>to raise</span>
<<elseif $parasite >= _hiveCost>>
<<button "Buy">><<run window.buyUpgrade("hivemindCap")>><<goto "Upgrades">><</button>>
<span class="upg-cost">☣ <<print _hiveCost>></span>
<<else>>
<span class="upg-locked">☣ <<print _hiveCost>><br><span style="color:#333;">need <<print _hiveCost - $parasite>> more</span></span>
<</if>>
</div>
</div>
/* ── EMERGENCY HIVEMIND — only once the normal path is exhausted ── */
<<set _emCost = window.getEmergencyHivemindCost ? window.getEmergencyHivemindCost() : null>>
<<if _emCost !== null>>
<div class="upg-row" style="background:#1a0a0a; border:1px solid #5a2a2a;">
<div class="upg-body">
<div class="upg-name" style="color:#ff8866;">⚠ Strained Expansion +1</div>
<div class="upg-desc">
<<print _hiveCurrent>> → <b style="color:#999;"><<print _hiveCurrent + 1>></b> · <span style="color:#aa6644;">+5 suspicion</span><br>
<span style="font-style:italic;">Force the hivemind past its natural ceiling. Expensive and it shows — but it will never leave you stuck with a full hivemind and a girl you must infect.</span>
</div>
</div>
<div class="upg-act">
<<if $parasite >= _emCost>>
<<button "Strain">><<run window.buyUpgrade("hivemindCapEmergency")>><<goto "Upgrades">><</button>>
<span class="upg-cost">☣ <<print _emCost>></span>
<<else>>
<span class="upg-locked">☣ <<print _emCost>><br><span style="color:#333;">need <<print _emCost - $parasite>> more</span></span>
<</if>>
</div>
</div>
<</if>>
/* ── LEVELLED: Universal Threshold ──
Was three rows in three different tiers. Drawn here with the other
repeatable purchases so the ladder and its cost are visible.
Old saves have the booleans but no level -- derive it for display
or the row reads 0/3 for someone who already owns two tiers. */
<<set _utLvl = $corrCapLevel>>
<<if _utLvl is undefined>>
<<set _utLvl = 0>>
<<for _utk to 1; _utk lte 3; _utk++>>
<<if $upgrades and $upgrades["corrCapUnlock" + _utk]>><<set _utLvl = _utk>><</if>>
<</for>>
<</if>>
<<set _utCosts = [20, 30, 50]>>
<<set _utCost = _utCosts[_utLvl]>>
<<set _utCaps = [25, 50, 75, 100]>>
<<set _utNeed = _utLvl + 2>>
<div class="upg-row" style="background:#1a1a2a;">
<div class="upg-body">
<div class="upg-name" style="color:#ddd;">🧬 Universal Threshold <<print _utLvl>> / 3</div>
<div class="upg-desc">
<<if _utLvl >= 3>>Every girl can reach Corr 100.
<<else>>Corruption ceiling <b style="color:#999;"><<print _utCaps[_utLvl]>></b> → <b style="color:#999;"><<print _utCaps[_utLvl + 1]>></b> · needs Parasite Level <<print _utNeed>>
<</if>>
</div>
</div>
<div class="upg-act">
<<if _utLvl >= 3>>
<span style="color:#2a5a2a; font-size:0.85em;">✓ Maxed</span>
<<elseif _lvl < _utNeed>>
<span class="upg-locked">Evolve<br>to raise</span>
<<elseif $parasite >= _utCost>>
<<button "Buy">><<run window.buyUpgrade("corrCapLevel")>><<goto "Upgrades">><</button>>
<span class="upg-cost">☣ <<print _utCost>></span>
<<else>>
<span class="upg-locked">☣ <<print _utCost>><br><span style="color:#333;">need <<print _utCost - $parasite>> more</span></span>
<</if>>
</div>
</div>
/* ── LEVELLED: Faction Directives ── */
<<set _fdLvl = $factionDirectiveLevel>>
<<if _fdLvl is undefined>>
<<set _fdLvl = 0>>
<<for _fdk to 1; _fdk lte 4; _fdk++>>
<<if $upgrades and $upgrades["factionDirectives" + _fdk]>><<set _fdLvl = _fdk>><</if>>
<</for>>
<</if>>
<<set _fdCosts = [10, 15, 18, 25]>>
<<set _fdCost = _fdCosts[_fdLvl]>>
<div class="upg-row" style="background:#1a1a2a;">
<div class="upg-body">
<div class="upg-name" style="color:#ddd;">⚡ Faction Directives <<print _fdLvl>> / 4</div>
<div class="upg-desc">
<<if _fdLvl >= 4>>Every directive unlocked.
<<else>>Unlocks <b style="color:#999;">Tier <<print _fdLvl + 1>></b> directives · needs Parasite Level <<print _fdLvl + 1>>
<</if>>
</div>
</div>
<div class="upg-act">
<<if _fdLvl >= 4>>
<span style="color:#2a5a2a; font-size:0.85em;">✓ Maxed</span>
<<elseif _fdLvl >= _lvl>>
<span class="upg-locked">Evolve<br>to raise</span>
<<elseif $parasite >= _fdCost>>
<<button "Buy">><<run window.buyUpgrade("factionDirectiveLevel")>><<goto "Upgrades">><</button>>
<span class="upg-cost">☣ <<print _fdCost>></span>
<<else>>
<span class="upg-locked">☣ <<print _fdCost>><br><span style="color:#333;">need <<print _fdCost - $parasite>> more</span></span>
<</if>>
</div>
</div>
<div class="upg-row" style="background:#1a1a2a;">
<div class="upg-body">
<div class="upg-name" style="color:#ddd;">☣ Infection Power +1</div>
<div class="upg-desc"><<print _infCurrent>> → <b style="color:#999;"><<print _infCurrent + 1>></b> · cap <<print _caps.infPower>> at this level</div>
</div>
<div class="upg-act">
<<if _infCurrent >= _caps.infPower>>
<span class="upg-locked">Evolve<br>to raise</span>
<<elseif $parasite >= _infCost>>
<<button "Buy">><<run window.buyUpgrade("infectionPower")>><<goto "Upgrades">><</button>>
<span class="upg-cost">☣ <<print _infCost>></span>
<<else>>
<span class="upg-locked">☣ <<print _infCost>><br><span style="color:#333;">need <<print _infCost - $parasite>> more</span></span>
<</if>>
</div>
</div>
</div>
</div>
/* ── EVOLUTION ── */
<<if _lvl < 4>>
<<set _evo = _evoReqs[_lvl + 1]>>
<<set _canEvo = _evo.met && $parasite >= _evo.cost>>
<div style="background:#111; border:2px solid <<if _canEvo>>#9c27b0<<else>>#1a0030<</if>>; border-radius:10px; padding:16px; margin-bottom:24px;">
<div style="font-size:0.8em; text-transform:uppercase; letter-spacing:0.1em; color:#6a0dad; margin-bottom:12px; font-weight:bold;">
Evolve → Level <<print _lvl + 1>> — <<print _lvlNames[_lvl + 1]>>
</div>
<div style="display:flex; flex-direction:column; gap:8px; margin-bottom:14px;">
<div style="display:flex; align-items:center; gap:10px;">
<span style="font-size:1.1em; color:<<if $parasite >= _evo.cost>>#44ff88<<else>>#ff5555<</if>>;"><<if $parasite >= _evo.cost>>✓<<else>>✗<</if>></span>
<span style="color:#bbb; font-size:0.95em;"><<print _evo.cost>> parasites</span>
<<if $parasite < _evo.cost>><span style="color:#555; font-size:0.85em;">(need <<print _evo.cost - $parasite>> more)</span><</if>>
</div>
<div style="display:flex; align-items:center; gap:10px;">
<span style="font-size:1.1em; color:<<if _evo.met>>#44ff88<<else>>#ff8844<</if>>;"><<if _evo.met>>✓<<else>>✗<</if>></span>
<span style="color:#bbb; font-size:0.95em;"><<print _evo.label>></span>
</div>
/* "1 Authority figure infected" meant nothing without knowing who
counts. It is a trait on the character record, not a group, so
the Characters page cannot be used to work it out. */
<<if _evo.label.includes("Authority")>>
<<set _authAll = $roster.filter(id => State.variables[id] && State.variables[id].trait is "authority")>>
<<set _authKnown = _authAll.filter(id => State.variables[id].met)>>
<div style="margin-left:26px; color:#666; font-size:0.82em; line-height:1.6;">
An <b style="color:#888;">Authority figure</b> is someone who could act against you — the police, the courthouse and the town hall. There <<if _authAll.length is 1>>is<<else>>are<</if>> <b><<print _authAll.length>></b> in the game.
<<if _authKnown.length > 0>>
<br>You have met: <span style="color:#888;"><<print _authKnown.map(id => State.variables[id].name + " (" + State.variables[id].corr + "%)").join(", ")>></span>.
<<else>>
<br><span style="color:#555;">You have not met any of them yet.</span>
<</if>>
</div>
<</if>>
</div>
<<if _canEvo>>
<div style="text-align:center;">
<<button "Evolve → " + _lvlNames[_lvl + 1]>>
<<run window.evoluteParasiteLevel()>>
<<goto "ParasiteLevelUpScene">>
<</button>>
</div>
<<else>>
<div style="text-align:center; color:#444; font-size:0.9em; font-style:italic;">Requirements not yet met.</div>
<</if>>
</div>
<<else>>
<div style="text-align:center; color:#ff5555; font-size:1em; font-style:italic; margin-bottom:24px;">Maximum evolution reached.</div>
<</if>>
/* ── TIER UPGRADES ── */
<<set _tiers = [
{ tier: 1, minLevel: 1, color: "#88aaff", label: "Tier I", subtitle: "Reconnaissance & Foundation" },
{ tier: 2, minLevel: 2, color: "#44cc88", label: "Tier II", subtitle: "Influence & Corruption" },
{ tier: 3, minLevel: 3, color: "#ffaa44", label: "Tier III", subtitle: "Control & Domination" },
{ tier: 4, minLevel: 4, color: "#ff5555", label: "Tier IV", subtitle: "Endgame" }
]>>
<<for _tier range _tiers>>
<<set _tierLocked = _lvl < _tier.minLevel>>
<div style="margin-bottom:24px;">
<div style="display:flex; align-items:center; gap:12px; margin-bottom:12px;">
<div style="width:44px; height:44px; border-radius:8px; flex-shrink:0;
background:<<if _tierLocked>>#111<<else>>#0d0018<</if>>;
border:2px solid <<if _tierLocked>>#222<<else>><<print _tier.color>><</if>>;
display:flex; align-items:center; justify-content:center;
font-weight:bold; font-size:0.85em;
color:<<if _tierLocked>>#333<<else>><<print _tier.color>><</if>>;">
<<print _tier.label>>
</div>
<div>
<div style="font-size:1em; font-weight:bold; color:<<if _tierLocked>>#333<<else>><<print _tier.color>><</if>>;">
<<print _tier.subtitle>>
</div>
<<if _tierLocked>>
<div style="font-size:0.82em; color:#333;">Unlocks at Parasite Level <<print _tier.minLevel>></div>
<<else>>
<<set _tierUpgrades = window.UPGRADE_DEFS.filter(u => u.tier === _tier.tier)>>
<<set _ownedCount = _tierUpgrades.filter(u => $upgrades && $upgrades[u.id] === true).length>>
<div style="font-size:0.82em; color:#555;"><<print _ownedCount>> / <<print _tierUpgrades.length>> owned</div>
<</if>>
</div>
</div>
<<if _tierLocked>>
<div style="background:#111; border:1px solid #1a1a1a; border-radius:8px; padding:14px; text-align:center; color:#333; font-size:0.9em; font-style:italic;">
Locked until Parasite Level <<print _tier.minLevel>>
</div>
<<else>>
<<set _tierUpgrades = window.UPGRADE_DEFS.filter(u => u.tier === _tier.tier)>>
<div style="display:flex; flex-direction:column; gap:6px;">
<<for _upg range _tierUpgrades>><<capture _upg>>
<<set _owned = ($upgrades && $upgrades[_upg.id] === true)>>
<<set _canBuy = !_owned && $parasite >= _upg.cost>>
<div class="upg-row" @style="'background:' + (_owned ? '#0d1a0d' : '#111') + '; border:1px solid ' + (_owned ? '#1a3a1a' : (_canBuy ? _tier.color + '44' : '#1a1a1a')) + ';'">
<div class="upg-body">
<div class="upg-name" @style="'color:' + (_owned ? '#44aa44' : '#ddd') + ';'">
<<if _owned>>✓ <</if>><<print _upg.name>>
</div>
<div class="upg-desc"><<print _upg.desc>></div>
</div>
<div class="upg-act">
<<if _owned>>
<span style="color:#2a5a2a; font-size:0.85em;">✓ Owned</span>
<<elseif _canBuy>>
<<capture _upg>>
<<button "Buy">>
<<run window.buyUpgrade(_upg.id)>>
<<goto "Upgrades">>
<</button>>
<</capture>>
<span class="upg-cost">☣ <<print _upg.cost>></span>
<<else>>
<span class="upg-locked">☣ <<print _upg.cost>><br><span style="color:#333;">need <<print _upg.cost - $parasite>> more</span></span>
<</if>>
</div>
</div>
<</capture>><</for>>
</div>
<</if>>
</div>
<</for>>
</div>
<</nobr>>/* =========================================================================
§ 12. UPGRADE SYSTEM
========================================================================= */
/* ── LEVEL CEILINGS ── */
window.PARASITE_LEVEL_CAPS = {
1: { nestCap: 5, hivemind: 10, infPower: 5, hivemindStep: 1 },
2: { nestCap: 7, hivemind: 25, infPower: 10, hivemindStep: 2 },
3: { nestCap: 10, hivemind: 50, infPower: 15, hivemindStep: 5 },
/* Apex is the end of the ladder — no ceiling worth calling one. Purchases
still cost parasites and the cost still scales, so growth is paced by
what you can afford rather than by a number in this table. 999 rather
than 9999 only so the figure fits the UI. */
4: { nestCap: 999, hivemind: 999, infPower: 999, hivemindStep: 10 }
};
/* ── EVOLUTION REQUIREMENTS ── */
window.EVOLUTION_REQS = {
2: {
cost: 10,
label: "3 girls at Corr 25",
check: function() {
var sv = State.variables;
return sv.roster.filter(function(id) {
return sv[id] && sv[id].corr >= 25;
}).length >= 3;
}
},
3: {
cost: 25,
/* Merely infecting an authority figure was a single action and could
be done the day you met her. Holding one at corr 50 means you have
actually kept her, which is the thing the level is meant to prove. */
label: "1 Authority figure at Corr 50",
check: function() {
var sv = State.variables;
return sv.roster.some(function(id) {
var c = sv[id];
return c && c.infected && c.trait === "authority" && c.corr >= 50;
});
}
},
4: {
cost: 50,
label: "5 locations dominated",
check: function() {
var sv = State.variables;
return ((sv.goalBonuses && sv.goalBonuses.corruptedLocations) || []).length >= 5;
}
}
};
/* ── UPGRADE DEFINITIONS ── */
window.UPGRADE_DEFS = [
/* ══ TIER 1 ══════════════════════════════════════════════════════════ */
{
id: "characterAgenda",
tier: 1,
name: "Character Agenda",
desc: "Unlock the Character Agenda — see where every known girl is located each day.",
cost: 4
},
{
id: "locationAgenda",
tier: 1,
name: "Location Agenda",
desc: "Unlock the Location Agenda — reveals nest status, pillars and domination for every location.",
cost: 5
},
{
id: "revealPortraits",
tier: 1,
name: "Distant Recognition",
desc: "Unmet girls appear as greyed silhouettes in the Characters screen.",
cost: 4
},
{
id: "locationDiscovery",
tier: 1,
name: "Location Discovery",
desc: "Increases the daily chance of new locations becoming accessible.",
cost: 6
},
{
id: "nestDuration1",
tier: 1,
name: "Nest Resilience I",
desc: "All nests last 50% longer before decaying.",
cost: 6
},
{
id: "infectionSuccessRate1",
tier: 1,
name: "Refined Strain I",
desc: "Direct infection success rate increased by 25%.",
cost: 5
},
/* ══ TIER 2 ══════════════════════════════════════════════════════════ */
{
id: "suspicionIntimate",
tier: 2,
name: "Intimate Veil",
desc: "Interactions in intimate locations generate 50% less suspicion.",
cost: 8
},
{
id: "suspicionSocialHub",
tier: 2,
name: "Social Cover",
desc: "Interactions in social hubs generate 50% less suspicion.",
cost: 8
},
{
id: "suspicionAcademic",
tier: 2,
name: "Academic Blind Spot",
desc: "Interactions in academic locations generate 50% less suspicion.",
cost: 8
},
{
id: "corrTickSocialHub",
tier: 2,
name: "Social Resonance",
desc: "Infected girls in social hub locations gain +1 corruption per night.",
cost: 10
},
{
id: "corrTickIntimate",
tier: 2,
name: "Intimate Bond",
desc: "Infected girls in intimate locations gain +1 corruption per night.",
cost: 10
},
{
id: "corrTickSameLocation",
tier: 2,
name: "Proximity Effect",
desc: "Spending time with one girl passively ticks all other infected girls at the same location.",
cost: 12
},
{
id: "nestDuration2",
tier: 2,
name: "Nest Resilience II",
desc: "All nests last an additional 50% longer (stacks with Resilience I).",
cost: 10
},
{
id: "factionParasiteGen1",
tier: 2,
name: "Faction Harvest I",
desc: "Each dominated faction generates +1 parasite per day automatically.",
cost: 12
},
{
id: "infectAuthority",
tier: 2,
name: "Authority Breach",
desc: "Unlocks the ability to infect Authority figures.",
cost: 20
},
{
id: "noPartySuspicion",
tier: 2,
name: "Discreet Gatherings",
desc: "Faction parties no longer generate suspicion.",
cost: 12
},
/* ══ TIER 3 ══════════════════════════════════════════════════════════ */
{
id: "noRandomSuspicion",
tier: 3,
name: "Controlled Behaviour",
desc: "Infected girls no longer trigger random suspicion events.",
cost: 15
},
{
id: "suspicionOutdoor",
tier: 3,
name: "Outdoor Discretion",
desc: "Interactions in outdoor and transient locations generate 50% less suspicion.",
cost: 10
},
{
id: "suspicionDecay",
tier: 3,
name: "Fading Traces",
desc: "Suspicion decays by 1 point per day passively.",
cost: 15
},
{
id: "noActivitySuspicion",
tier: 3,
name: "Crowd Cover",
desc: "Activities (Arcade, Cinema, Spa, etc.) no longer generate suspicion.",
cost: 15
},
{
id: "corrTickGlobal",
tier: 3,
name: "Deepening Roots",
desc: "All infected girls gain +1 corruption per night regardless of location.",
cost: 18
},
{
id: "corrTickSocialHub2",
tier: 3,
name: "Social Resonance II",
desc: "Infected girls in social hubs gain an additional +2 corruption per night (stacks).",
cost: 15
},
{
id: "corrTickIntimate2",
tier: 3,
name: "Intimate Bond II",
desc: "Infected girls in intimate locations gain an additional +2 corruption per night (stacks).",
cost: 15
},
{
id: "corrTickSameLocation2",
tier: 3,
name: "Proximity Effect II",
desc: "Spending time with one girl actively ticks all other infected girls at the same location.",
cost: 18
},
{
id: "nestCritical",
tier: 3,
name: "Deep Infiltration",
desc: "Allows placing nests at critical locations, provided 100% of pillars are qualified.",
cost: 20
},
{
id: "nestDecayOutdoor",
tier: 3,
name: "Rooted Network",
desc: "Nests in outdoor and transient locations decay at half the normal rate.",
cost: 12
},
{
id: "noArrest",
tier: 3,
name: "Protected Network",
desc: "Infected girls can no longer be arrested.",
cost: 25
},
{
id: "passiveSpread",
tier: 3,
name: "Whisper Network",
desc: "Infected girls at corruption 50+ deepen their infected friends by +1 each night. Does not create new hosts.",
cost: 20
},
{
id: "locControlSocialHub",
tier: 3,
name: "Location Control: Social Hub",
desc: "Dominated social hub locations: 10% chance any uninfected visitor catches the parasite passively.",
cost: 18
},
{
id: "locControlAcademic",
tier: 3,
name: "Location Control: Academic",
desc: "Dominated academic locations: +2 corruption daily for all girls anchored there.",
cost: 18
},
{
id: "locControlIntimate",
tier: 3,
name: "Location Control: Intimate",
desc: "Dominated intimate locations: suspicion gain reduced 50% specifically at that location.",
cost: 18
},
{
id: "locControlOutdoor",
tier: 3,
name: "Location Control: Outdoor",
desc: "Dominated outdoor and transient locations: nest decay rate halved there.",
cost: 15
},
{
id: "locControlCritical",
tier: 3,
name: "Location Control: Critical",
desc: "Nests placed at dominated critical locations generate no suspicion events.",
cost: 20
},
{
id: "collectiveWill",
tier: 3,
name: "Collective Will",
desc: "Faction stability now scales with the corruption of the faction leader.",
cost: 15
},
{
id: "factionParasiteGen2",
tier: 3,
name: "Faction Harvest II",
desc: "Each dominated faction generates an additional +2 parasites per day (stacks with Harvest I).",
cost: 18
},
/* ══ TIER 4 ══════════════════════════════════════════════════════════ */
{
id: "infectUnmet",
tier: 4,
name: "Blind Reach",
desc: "Allows infecting girls you haven't yet met.",
cost: 20
},
{
id: "vectors",
tier: 4,
name: "Vector Protocol",
desc: "Girls at corr 100 become Vectors — they actively spread infection to their connections each night.",
cost: 30
},
{
id: "highCorrNoSuspicion",
tier: 4,
name: "Perfect Compliance",
desc: "Girls at corr 75+ generate no suspicion during interactions.",
cost: 20
},
{
id: "globalSuspicionReduce",
tier: 4,
name: "Shadow Presence",
desc: "All suspicion gain reduced by 25% globally.",
cost: 20
},
{
id: "corrTickEverywhere",
tier: 4,
name: "Total Saturation",
desc: "All infected girls gain +2 corruption per night everywhere (stacks with all other tick upgrades).",
cost: 25
},
{
id: "nestBreedingBoost",
tier: 4,
name: "Breeding Surge",
desc: "Breeding nests generate +2 parasites per night instead of +1.",
cost: 20
},
{
id: "nestsNeverDecay",
tier: 4,
name: "Eternal Roots",
desc: "Nests in safe locations never decay.",
cost: 30
},
{
id: "locDominatedSpread",
tier: 4,
name: "Territorial Infection",
desc: "All uninfected girls entering a dominated location have a 25% chance of catching the parasite.",
cost: 25
},
{
id: "factionAutoSpread",
tier: 3,
name: "Enthralled Agents",
desc: "Each night, one member of an enthralled faction may take a girl she is co-located with — infecting her and holding her captive for 5 days. You approve each abduction in the morning; taking her costs +10 suspicion.",
cost: 25
},
{
id: "factionAutoSpread2",
tier: 4,
name: "Enthralled Agents II",
desc: "Up to three enthralled agents can act each night instead of one. Each abduction is approved separately and costs +10 suspicion.",
cost: 30
},
{
id: "factionParasiteGen3",
tier: 4,
name: "Faction Harvest III",
desc: "Each dominated faction generates an additional +3 parasites per day (stacks with Harvest I & II).",
cost: 22
}
];
/* ── EVOLVE PARASITE LEVEL ── */
window.evoluteParasiteLevel = function() {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
if (lvl >= 4) return false;
var req = window.EVOLUTION_REQS[lvl + 1];
if (!req) return false;
if (!req.check()) return false;
if (sv.parasite < req.cost) return false;
sv.parasite -= req.cost;
sv.parasiteLevel = lvl + 1;
/* Evolving grants a step up, but never past the new level's ceiling —
otherwise the free grant could overshoot the cap it just unlocked. */
var newCaps = window.PARASITE_LEVEL_CAPS[sv.parasiteLevel] || {};
sv.nestCap = Math.min(newCaps.nestCap || 9999, (sv.nestCap || 2) + 2);
sv.hivemindCap = Math.min(newCaps.hivemind || 9999, (sv.hivemindCap || 5) + 10);
sv.infectionPower = Math.min(newCaps.infPower || 9999, (sv.infectionPower || 1) + 1);
/* Queue level-up scene */
sv.pendingLevelUpScene = sv.parasiteLevel;
return true;
};
/* ── BUY UPGRADE ── */
window.buyUpgrade = function(id) {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
var caps = window.PARASITE_LEVEL_CAPS[lvl];
if (!caps) return false;
/* ── REPEATABLE: Nest Cap ── */
if (id === "nestCap") {
var current = sv.nestCap || 2;
if (current >= caps.nestCap) return false;
var cost = 3 + (current * 2);
if (sv.parasite < cost) return false;
sv.parasite -= cost;
sv.nestCap = current + 1;
return true;
}
/* ── REPEATABLE: Hivemind Cap ── */
if (id === "hivemindCap") {
var current = sv.hivemindCap || 5;
if (current >= caps.hivemind) return false;
var cost = 2 + Math.floor(current / 5);
if (sv.parasite < cost) return false;
sv.parasite -= cost;
sv.hivemindCap = current + caps.hivemindStep;
return true;
}
/* ── EMERGENCY: Strained Expansion ──
Only usable once the normal hivemind purchase is exhausted for this
parasite level. Grants +1 slot at a steeply escalating price so the
player can never be permanently softlocked by a full hivemind. ── */
if (id === "hivemindCapEmergency") {
var cur = sv.hivemindCap || 5;
var overage = cur - caps.hivemind;
if (overage < 0) return false; /* normal path still open */
var ecost = 15 + (overage * 10); /* 15, 25, 35, 45 … */
if (sv.parasite < ecost) return false;
sv.parasite -= ecost;
sv.hivemindCap = cur + 1;
window.addSuspicion(5); /* the strain shows */
return true;
}
/* ── REPEATABLE: Infection Power ── */
/* ── LEVELLED: Universal Threshold ────────────────────────────────────
Was three separate upgrades (corrCapUnlock1/2/3) in tiers 2, 3 and 4.
They are strictly sequential -- II raises a ceiling I has already
lifted -- so buying them in order was never a choice, and as three
rows the ladder was invisible. One levelled purchase, drawn like
Infection Power and the two caps.
$corrCapLevel is the number of thresholds lifted:
0 -> cap 25, 1 -> 50, 2 -> 75, 3 -> 100
The three booleans are STILL WRITTEN. getGlobalCorrCap() reads them,
and any save made before this change already carries them -- derive
first, then only ever set true, so a player who owns two tiers cannot
be silently dropped to one.
Tier 1 was a tier-2 upgrade, tier 2 a tier-3, tier 3 a tier-4, so each
level needs parasite level ccur + 2. The original gating, unchanged.
────────────────────────────────────────────────────────────────── */
if (id === "corrCapLevel") {
if (sv.corrCapLevel === undefined) {
var cderived = 0;
for (var ck = 1; ck <= 3; ck++) {
if (sv.upgrades["corrCapUnlock" + ck]) cderived = ck;
}
sv.corrCapLevel = cderived;
}
var ccur = sv.corrCapLevel || 0;
if (ccur >= 3) return false;
if (lvl < ccur + 2) return false;
var ccost = [20, 30, 50][ccur];
if (sv.parasite < ccost) return false;
sv.parasite -= ccost;
sv.corrCapLevel = ccur + 1;
for (var ci = 1; ci <= sv.corrCapLevel; ci++) {
sv.upgrades["corrCapUnlock" + ci] = true;
}
return true;
}
/* ── LEVELLED: Faction Directives ─────────────────────────────────────
Was four separate upgrades across three tiers. Same reasoning: II is
useless without I, so it is one levelled purchase.
$factionDirectiveLevel is the number of tiers unlocked. The four
boolean flags are still written because getAvailableDirectives() and
issueDirective() both read them, and old saves carry them. Derive
before setting, for the same reason as above.
Costs 10/15/18/25 and the level requirement are the originals.
────────────────────────────────────────────────────────────────── */
if (id === "factionDirectiveLevel") {
if (sv.factionDirectiveLevel === undefined) {
var derived = 0;
for (var dk = 1; dk <= 4; dk++) {
if (sv.upgrades["factionDirectives" + dk]) derived = dk;
}
sv.factionDirectiveLevel = derived;
}
var dcur = sv.factionDirectiveLevel || 0;
if (dcur >= 4) return false;
if (dcur >= lvl) return false; /* never past parasite level */
var dcost = [10, 15, 18, 25][dcur];
if (sv.parasite < dcost) return false;
sv.parasite -= dcost;
sv.factionDirectiveLevel = dcur + 1;
for (var di = 1; di <= sv.factionDirectiveLevel; di++) {
sv.upgrades["factionDirectives" + di] = true;
}
return true;
}
if (id === "infectionPower") {
var current = sv.infectionPower || 1;
if (current >= caps.infPower) return false;
var cost = 2 + (current * 2);
if (sv.parasite < cost) return false;
sv.parasite -= cost;
sv.infectionPower = current + 1;
return true;
}
/* ── ONE-TIME UPGRADES ── */
if (!sv.upgrades) return false;
if (sv.upgrades[id] === true) return false;
var def = window.UPGRADE_DEFS.find(function(u) { return u.id === id; });
if (!def) return false;
if (def.tier > lvl) return false;
if (sv.parasite < def.cost) return false;
sv.parasite -= def.cost;
sv.upgrades[id] = true;
return true;
};
/* ── UPGRADE ACTIVE CHECK ── */
window.hasUpgrade = function(id) {
var sv = State.variables;
if (!sv.upgrades) return false;
return !!sv.upgrades[id];
};
/* ── GET CORRUPTION CAP FOR A GIRL ──
Called with no argument -> the GLOBAL cap from upgrades (legacy behaviour).
Called with a girl id or character object -> that girl's EFFECTIVE cap,
which is the global cap plus any per-girl breaks purchased via "Break Cap".
c.capBreaks = number of 25-point tiers unlocked for that girl specifically.
────────────────────────────────────────────────────────────────────── */
window.getGlobalCorrCap = function() {
var ups = State.variables.upgrades || {};
/* Level first; the booleans are the old-save fallback and are also
written by the levelled purchase, so the two cannot disagree. */
var clv = State.variables.corrCapLevel;
if (clv !== undefined) {
if (clv >= 3) return 100;
if (clv >= 2) return 75;
if (clv >= 1) return 50;
}
if (ups.corrCapUnlock3) return 100;
if (ups.corrCapUnlock2) return 75;
if (ups.corrCapUnlock1) return 50;
return 25;
};
window.getCorrCap = function(who) {
var base = window.getGlobalCorrCap();
if (who === undefined || who === null) return base;
var sv = State.variables;
var c = (typeof who === "string") ? sv[who] : who;
if (!c) return base;
var breaks = c.capBreaks || 0;
return Math.min(100, base + (breaks * 25));
};
/* ── BREAK A GIRL'S CAP ──
Raises this girl's personal ceiling by one 25-point tier.
Returns the new effective cap, or null if she is already at 100. ── */
window.breakCorrCap = function(id) {
var sv = State.variables;
var c = sv[id];
if (!c) return null;
if (window.getCorrCap(c) >= 100) return null;
c.capBreaks = (c.capBreaks || 0) + 1;
return window.getCorrCap(c);
};
/* ── DAILY UPGRADE EFFECTS ── */
window.processUpgradeEffects = function(log) {
var sv = State.variables;
var ups = sv.upgrades || {};
var roster = sv.roster;
/* ── Faction parasite generation ── */
var factionParasitePerDay = 0;
if (ups.factionParasiteGen1) factionParasitePerDay += 1;
if (ups.factionParasiteGen2) factionParasitePerDay += 2;
if (ups.factionParasiteGen3) factionParasitePerDay += 3;
if (factionParasitePerDay > 0) {
var dominatedFactions = (sv.factions || []).filter(function(f) {
return f.stance === "dominated";
}).length;
if (dominatedFactions > 0) {
var gain = dominatedFactions * factionParasitePerDay;
sv.parasite += gain;
log.push('<span style="color:#bd59ff;">🏛 Dominated factions yielded +' + gain + ' parasite.</span>');
}
}
/* ── Suspicion decay ── */
if (ups.suspicionDecay && (sv.suspicion || 0) > 0) {
sv.suspicion = Math.max(0, sv.suspicion - 1);
}
/* ── Whisper Network (passiveSpread) ──
Deepens ALREADY-INFECTED contacts only. It must never create a new
host: silent infections that eat hivemind slots the player never
authorised were a bug, not a feature. Always reported. */
if (ups.passiveSpread) {
var whisperHits = [];
roster.forEach(function(id) {
var c = sv[id];
if (!c || !c.infected || c.corr < 50 || c.arrested) return;
(c.connections || []).forEach(function(cid) {
var cc = sv[cid];
if (!cc || cc.arrested) return;
if (!cc.infected) return; /* infected only — no new hosts */
var cap = window.getCorrCap(cc);
if (cc.corr >= cap) return;
if (Math.random() < 0.15) {
cc.corr = Math.min(cap, cc.corr + 1);
whisperHits.push(cc.met ? cc.name : "someone");
}
});
});
if (whisperHits.length > 0) {
log.push('<span style="color:#cc88ff;">🕸 <b>Whisper Network</b> deepened ' +
whisperHits.join(', ') + ' (+1).</span>');
}
}
/* ── Location control: socialHub passive infection ── */
if (ups.locControlSocialHub) {
var dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
roster.forEach(function(id) {
var c = sv[id];
if (!c || c.infected || c.arrested) return;
/* Location Control infects passers-by with no player action. */
if (!window.canInfect(c) || !window.autoInfectOn()) return;
var loc = c.location;
var trait = (window.LOCATION_TRAITS && loc) ? (window.LOCATION_TRAITS[loc] || "") : "";
if (!loc || dominated.indexOf(loc) === -1 || trait !== "socialHub") return;
if (Math.random() < 0.10) {
window.recordInfection(c, "upgrade", loc);
if (c.corr === 0) c.corr = 1;
log.push('<span style="color:#bd59ff;">🏙 <b>Location Control</b> — ' +
(c.met ? '<b>' + c.name + '</b>' : 'someone') +
' was passively infected at <b>' + loc + '</b>.</span>');
}
});
}
/* ── Location control: academic +2 corr ── */
if (ups.locControlAcademic) {
var dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
roster.forEach(function(id) {
var c = sv[id];
if (!c || !c.infected || c.arrested) return;
var cap = window.getCorrCap(c);
if (c.corr >= cap) return;
var loc = c.location;
var trait = (window.LOCATION_TRAITS && loc) ? (window.LOCATION_TRAITS[loc] || "") : "";
if (!loc || dominated.indexOf(loc) === -1 || trait !== "academic") return;
c.corr = Math.min(cap, c.corr + 2);
});
}
/* ── Location control: dominated spread (25%) ── */
if (ups.locDominatedSpread) {
var dominated = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
roster.forEach(function(id) {
var c = sv[id];
if (!c || c.infected || c.arrested) return;
/* Territorial Infection -- likewise automatic. */
if (!window.canInfect(c) || !window.autoInfectOn()) return;
if (dominated.indexOf(c.location) === -1) return;
if (Math.random() < 0.25) {
window.recordInfection(c, "upgrade", c.location);
if (c.corr === 0) c.corr = 1;
log.push('<span style="color:#bd59ff;">🗺 <b>Territorial Infection</b> — ' +
(c.met ? '<b>' + c.name + '</b>' : 'someone') +
' caught the parasite at <b>' + c.location + '</b>.</span>');
}
});
}
/* ── Collective Will ── */
if (ups.collectiveWill) {
(sv.factions || []).forEach(function(f) {
var leader = sv[f.leader];
if (!leader) return;
var target = 40 + Math.floor(leader.corr * 0.5);
if (f.stability < target) f.stability = Math.min(100, f.stability + 2);
});
}
};
/* ── PASSIVE CORRUPTION TICK BONUS ── */
window.getUpgradeCorrBonus = function(charId, location) {
var sv = State.variables;
var ups = sv.upgrades || {};
var bonus = 0;
var trait = (window.LOCATION_TRAITS && location)
? (window.LOCATION_TRAITS[location] || "") : "";
if (ups.corrTickSocialHub && trait === "socialHub") bonus += 1;
if (ups.corrTickIntimate && trait === "intimate") bonus += 1;
if (ups.corrTickGlobal) bonus += 1;
if (ups.corrTickSocialHub2 && trait === "socialHub") bonus += 2;
if (ups.corrTickIntimate2 && trait === "intimate") bonus += 2;
if (ups.corrTickEverywhere) bonus += 2;
return bonus;
};
/* ── SUSPICION MULTIPLIER ── */
/* context: optional string — "party" or "activity" for event-specific immunity */
window.getUpgradeSuspicionMult = function(location, context) {
var sv = State.variables;
var ups = sv.upgrades || {};
var trait = (window.LOCATION_TRAITS && location)
? (window.LOCATION_TRAITS[location] || "") : "";
var mult = 1.0;
/* Event-specific immunity */
if (context === "party" && ups.noPartySuspicion) return 0;
if (context === "activity" && ups.noActivitySuspicion) return 0;
if (ups.suspicionIntimate && trait === "intimate") mult *= 0.5;
if (ups.suspicionSocialHub && trait === "socialHub") mult *= 0.5;
if (ups.suspicionAcademic && trait === "academic") mult *= 0.5;
if (ups.suspicionOutdoor && (trait === "outdoor" || trait === "transient")) mult *= 0.5;
if (ups.globalSuspicionReduce) mult *= 0.75;
return mult;
};
/* ── EMERGENCY HIVEMIND: cost + availability for the Upgrades UI ── */
window.getEmergencyHivemindCost = function() {
var sv = State.variables;
var lvl = sv.parasiteLevel || 1;
var caps = window.PARASITE_LEVEL_CAPS[lvl];
if (!caps) return null;
var cur = sv.hivemindCap || 5;
var overage = cur - caps.hivemind;
if (overage < 0) return null; /* normal upgrade still available */
return 15 + (overage * 10);
};<<nobr>>
<<if !$levelUpTarget or !$levelUpStage>><<goto "TownHub">><</if>>
<<set _c = State.variables[$levelUpTarget]>>
<<if !_c>><<goto "TownHub">><</if>>
<<set _stage = $levelUpStage>>
<<set _img = window.getEventImagePath(_c.name)>>
<<set _stageData = {
"Corr1": { label: "Curious", color: "#88aaff", icon: "💭", summary: "Something has shifted in her. She's more aware of you now — watching, wondering." },
"Corr2": { label: "Receptive", color: "#bd59ff", icon: "🌀", summary: "The parasite has taken hold. She no longer questions the pull she feels toward you." },
"Corr3": { label: "Devoted", color: "#ff88cc", icon: "🩸", summary: "She is yours. The last walls have fallen. There is nothing she would refuse you." },
"Corr4": { label: "Vector", color: "#ff4444", icon: "☣", summary: "There is no line left between her and the parasite. Nothing in her is pulling the other way any more, and it holds her completely." }
}>>
<<set _data = _stageData[_stage]>>
<<if !_data>><<goto "TownHub">><</if>>
<<set _corrCap = window.getCorrCap ? window.getCorrCap($levelUpTarget) : 25>>
<<set _ret = $levelUpReturn || "TownHub">>
<</nobr>>
<div style="text-align:center; padding:0 20px 32px;">
<div style="border-bottom:2px solid <<print _data.color>>; padding-bottom:14px; margin-bottom:24px;">
<div style="font-size:0.75em; color:#555; text-transform:uppercase; letter-spacing:0.12em; margin-bottom:6px;">Stage Reached</div>
<h1 style="margin:0; color:<<print _data.color>>; font-size:2em;"><<print _data.icon>> <<print _data.label>></h1>
<div style="color:#666; font-size:0.85em; margin-top:4px;"><<print _c.name>></div>
</div>
<div style="margin-bottom:24px;">
<img @src="_img" style="max-width:340px; width:85%; border-radius:10px; border:3px solid <<print _data.color>>; display:block; margin:0 auto;">
</div>
<div style="background:#0d0d1a; border-left:3px solid <<print _data.color>>; border-radius:0 6px 6px 0; padding:14px 18px; margin:0 auto 24px; max-width:480px; font-style:italic; color:#ccc; line-height:1.7; font-size:0.92em; text-align:left;">
<<print _data.summary>>
</div>
/* What reaching 100 actually grants. Stated once, here, at the moment it
happens — it used to be a label with nothing behind it unless the
player had already bought Vector Protocol. */
<<if _stage is "Corr4">>
<div style="background:#12000a; border:1px solid #ff4444; border-radius:8px; padding:14px 18px; margin:0 auto 24px; max-width:480px; text-align:left;">
<div style="color:#ff4444; font-weight:bold; font-size:0.95em; margin-bottom:8px;">☣ She is one with the parasite</div>
<div style="color:#bbb; font-size:0.88em; line-height:1.7;">
<b style="color:#ddd;">She cannot be pushed further.</b> This is the deepest hold there is. She still occupies a hivemind slot — the parasite holds her completely, not cheaply — but nothing can loosen its grip on her now.
<br><br>
<b style="color:#ddd;">The Lab cannot touch her.</b> She can still be arrested, but there is no infection left to strip out. Every test comes back clean and they release her after <b>5 days</b>, still yours, still at 100.
<<if !($upgrades && $upgrades.vectors)>>
<br><br>
<span style="color:#777;">With the <b style="color:#999;">Vector Protocol</b> upgrade she would also spread the parasite to her own connections each night, unprompted.</span>
<</if>>
</div>
</div>
<</if>>
/* ── STAGE PROGRESSION BAR ── */
<div style="max-width:400px; margin:0 auto 20px;">
<div style="display:flex; align-items:flex-start; margin-bottom:8px;">
<<set _stages = ["Normal","Corr1","Corr2","Corr3","Corr4"]>>
<<set _stageLabels = { "Normal":"Unaware","Corr1":"Curious","Corr2":"Receptive","Corr3":"Devoted","Corr4":"Vector" }>>
<<set _stageColors = { "Normal":"#333","Corr1":"#88aaff","Corr2":"#bd59ff","Corr3":"#ff88cc","Corr4":"#ff4444" }>>
<<for _s range _stages>>
<<set _isCurrent = _s is _stage>>
<<set _isPast = _stages.indexOf(_s) < _stages.indexOf(_stage)>>
<div style="flex:1; text-align:center;">
<div style="width:12px; height:12px; border-radius:50%; margin:0 auto 3px; background:<<if _isCurrent>><<print _stageColors[_s]>><<elseif _isPast>>#2a2a2a<<else>>#111<</if>>; border:2px solid <<if _isCurrent>><<print _stageColors[_s]>><<elseif _isPast>>#3a3a3a<<else>>#1a1a1a<</if>>;"></div>
<div style="font-size:0.58em; color:<<if _isCurrent>><<print _stageColors[_s]>><<elseif _isPast>>#444<<else>>#222<</if>>;"><<print _stageLabels[_s]>></div>
</div>
<</for>>
</div>
<div style="background:#111; height:4px; border-radius:2px; overflow:hidden;">
<div @style="'width:' + _c.corr + '%; height:100%; background:' + _data.color + '; transition:width 0.5s;'"></div>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.65em; color:#333; margin-top:3px;">
<span>0</span><span>25</span><span>50</span><span>75</span><span>100</span>
</div>
<div style="text-align:right; font-size:0.72em; color:#555; margin-top:4px;">
Corruption: <<print _c.corr>>%
<<if _c.corr < 100>>
· Cap: <<print _corrCap>>
<<if _c.corr >= _corrCap>>
<span style="color:#bd59ff;"> — at cap, break to continue</span>
<</if>>
<</if>>
</div>
</div>
<div style="text-align:center;">
<<button "Continue">>
<<set $levelUpTarget = null>>
<<set $levelUpStage = null>>
<<set $levelUpReturn = null>>
<<goto _ret>>
<</button>>
</div>
</div><<nobr>>
<<set _entry = $availableScenes ? $availableScenes[$sceneLocation] : null>>
<<if _entry and _entry.type is "location">>
<<set $activeSceneID = _entry.sceneId>>
<<set $sceneTier = _entry.tier>>
<<set $sceneGroup = _entry.chars>>
<<if !$seenScenes>><<set $seenScenes = {}>><</if>>
<<set $seenScenes[_entry.key] = true>>
<<set $availableScenes[$sceneLocation] = null>>
<<goto _entry.target>>
<<else>>
<<goto "TownHub">>
<</if>>
<</nobr>><<nobr>>
<<set _c = State.variables[$sceneTarget]>>
<<set _img = window.getEventImagePath(_c.name)>>
<<set _context = $sceneContext || "">>
<<set _corrColor = {
"Normal": "#555",
"Corr1": "#88aaff",
"Corr2": "#bd59ff",
"Corr3": "#ff88cc",
"Corr4": "#ff4444"
}[window.getCorrSuffix(_c.corr)] || "#555">>
<</nobr>>
<div style="padding:0 20px 32px;">
<div style="border-bottom:2px solid <<print _corrColor>>; padding-bottom:12px; margin-bottom:20px; text-align:center;">
<div style="font-size:0.75em; color:#555; text-transform:uppercase; letter-spacing:0.12em; margin-bottom:4px;">
<<if _context>><<print _context>><<else>>Scene<</if>>
</div>
<h1 style="margin:0; color:<<print _corrColor>>; font-size:1.6em;"><<print _c.name>></h1>
<div style="color:#555; font-size:0.8em; margin-top:4px;"><<print _c.group>></div>
</div>
/* ── PORTRAIT ── */
<div style="margin-bottom:20px; text-align:center;">
<img @src="_img" style="max-width:320px; width:80%; border-radius:10px; border:2px solid <<print _corrColor>>; display:block; margin:0 auto;">
</div>
/* ── SCENE TEXT ── */
/* Write scene prose here. Use <<speech $sceneTarget>> for her dialogue. */
<div style="color:#ccc; line-height:1.8; font-size:0.92em; max-width:560px; margin:0 auto 24px;">
[Scene text goes here.]
</div>
/* ── OPTIONAL: CHOICES ── */
/* Remove this block if the scene has no player choices. */
/*
<div style="display:flex; flex-direction:column; gap:8px; max-width:400px; margin:0 auto 24px;">
<<button "Choice A">>
[apply effect A]
<<set $sceneTarget = null>>
<<set $sceneContext = null>>
<<goto $sceneReturn || "TownHub">>
<</button>>
<<button "Choice B">>
[apply effect B]
<<set $sceneTarget = null>>
<<set $sceneContext = null>>
<<goto $sceneReturn || "TownHub">>
<</button>>
</div>
*/
/* ── CONTINUE ── */
<div style="text-align:center;">
<<button "Continue">>
<<set $sceneTarget = null>>
<<set $sceneContext = null>>
<<goto $sceneReturn || "TownHub">>
<</button>>
</div>
</div><<nobr>>
<<set _entry = $availableScenes ? $availableScenes[$sceneLocation] : null>>
<<if _entry and _entry.type is "suspicion">>
<<set _s = window.findValidSuspicionScene($sceneLocation)>>
<<if _s>>
/* The scene bodies switch on $activeSceneID, which is keyed by
LOCATION NAME in SUS_DATA. Without this the switch matched nothing
and the passage rendered its frame with no scene text at all. */
<<set $activeSceneID = $sceneLocation>>
<<set $activeSuspicionAgent = _s.agent>>
<<set $activeSuspicionResidents = _s.res>>
<<set $activeSuspicionThreshold = _s.req>>
<<set $sceneGroup = _s.res>>
/* Mark it seen so the same one doesn't re-roll every night */
<<if !$seenScenes>><<set $seenScenes = {}>><</if>>
<<set $seenScenes["SUS-" + $sceneLocation] = true>>
<<set $availableScenes[$sceneLocation] = null>>
<<goto _s.target>>
<<else>>
<<goto "TownHub">>
<</if>>
<<else>>
<<goto "TownHub">>
<</if>>
<</nobr>>
<<nobr>>
<<set _loc = $sceneLocation>>
<<set _id = $activeSceneID>>
<<set _agent = $activeSuspicionAgent>>
<<set _res = $activeSuspicionResidents>>
<<set _threshold = $activeSuspicionThreshold>>
<<set _color = "#ff4444">>
<</nobr>>
<div style="padding:0 20px 32px;">
<div @style="'border-bottom:2px solid ' + _color + '; padding-bottom:12px; margin-bottom:20px; text-align:center;'">
<div style="font-size:0.75em; color:#ff8888; text-transform:uppercase; letter-spacing:0.12em; margin-bottom:4px;">⚠ High Risk Detection</div>
<h1 @style="'margin:0; color:' + _color + '; font-size:1.6em;'"><<print _loc>></h1>
</div>
/* _res is an ARRAY of character ids — never pass it to getPortraitPath()
directly, it calls .toLowerCase() on it. Render one card per resident. */
<<set _resList = Array.isArray(_res) ? _res : (_res ? [_res] : [])>>
<div style="display:flex; justify-content:center; align-items:center; gap:20px; margin-bottom:20px; flex-wrap:wrap;">
<div style="text-align:center;">
<img @src="window.getPortraitPath(_agent)" style="width:120px; border:2px solid #ff4444; border-radius:8px;">
<div style="font-size:0.8em; color:#ff4444; margin-top:5px;">AUTHORITY</div>
</div>
<div style="align-self:center; font-size:2em; color:#ff4444;">vs</div>
<<for _rid range _resList>>
<<capture _rid>>
<<set _rc = State.variables[_rid]>>
<<if _rc>>
<div style="text-align:center;">
<img @src="window.getPortraitPath(_rid)" style="width:120px; border:2px solid #9c27b0; border-radius:8px;">
<div style="font-size:0.8em; color:#9c27b0; margin-top:5px;">CORRUPTED (<<print _rc.corr>>%)</div>
</div>
<</if>>
<</capture>>
<</for>>
</div>
<div class="narrative-box" style="color:#eee; line-height:1.8; font-size:0.95em; max-width:650px; margin:0 auto 24px; border:1px solid #440000; padding:15px; background:rgba(20,0,0,0.8);">
/* ── CAST STRIP ──────────────────────────────────────────────────────────
Sized to match LocationScene-Header: fluid tiles that divide the row,
min 100px / max 200px, rather than the old fixed 150x198.
The agent is drawn whether or not she has been MET. All three suspicion
agents (Angel, Jane, Ember) start met:false, so gating her tile on .met
meant the investigating officer had no portrait in the majority of
scenes — including every two-girl scene, which is most of them.
─────────────────────────────────────────────────────────────────────── */
<<set _agentC = $activeSuspicionAgent ? State.variables[$activeSuspicionAgent] : null>>
<div style="display:flex; gap:12px; justify-content:center; align-items:flex-end; flex-wrap:wrap; margin-bottom:24px;">
<<if _agentC>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getEventImagePath(_agentC.name)" style="width:100%; border-radius:8px; border:2px solid #ff4444; display:block;">
<div style="color:#ff4444; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _agentC.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Investigating</div>
</div>
<</if>>
<<if $sceneGroup and $sceneGroup.length > 0>>
<<for _pgid range $sceneGroup>>
<<set _pgc = State.variables[_pgid]>>
<<if _pgc and _pgc.met>>
<<capture _pgid>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getEventImagePath(_pgc.name)" style="width:100%; border-radius:8px; border:2px solid #9933cc; display:block;">
<div style="color:#cc88ff; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _pgc.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Corr: <<print _pgc.corr>>%</div>
</div>
<</capture>>
<</if>>
<</for>>
<</if>>
</div>
<<switch _id>>
<<case "House">>
/* Jane (Agent) inspecting Jewelz (Resident) - Req 75 */
You have Jewelz bent over the kitchen counter with your cock buried deep inside her when the knock comes. She barely gets her dress down before Officer Jane lets herself in — she's been letting herself into kitchens on this street for years and nobody has ever minded.
Jewelz smooths her hair with trembling hands, cheeks flushed, breathing heavier than she'd like. Her thighs are still slick with your cum and she leans back against the counter to hide it.
<<speech "Jewelz">>(forcing the warm, tired smile) "Officer Jane. Is something wrong?"<</speech>>
<<speech "Jane">>"Nothing's wrong. Wellness check — I'm doing the whole street, don't read anything into it."<</speech>>
She says it easily enough, but her friendly expression has shifted. She's noticed the way Jewelz's legs are pressed together, the sheen of sweat on her collarbone, the tremble under the voice.
<<speech "Jane">>"You've seemed off lately, though. Everything alright at home?"<</speech>>
<<speech "$name">>"She's been working doubles again."<</speech>>
<<speech "Jane">>"Has she."<</speech>>
<<speech "Jewelz">>(a quick, submissive glance at you before she answers) "Everything's fine. $name's been taking such good care of me. Of all of us."<</speech>>
Her voice wavers on it as another small aftershock runs through her, and she has to grip the counter edge to ride it out.
Jane watches her do it. Whatever conclusion she reaches, she doesn't reach it out loud.
<<speech "Jane">>"Right."<</speech>>
<<speech "Jane">>(a beat) "You'd say, wouldn't you. If something wanted saying."<</speech>>
<<speech "Jewelz">>"There's nothing."<</speech>>
<<speech "Jane">>"Course."<</speech>>
She heads for the door and then pauses with a hand on the frame, and glances back at the kitchen itself rather than at either of you.
<<speech "Jane">>"Is your boiler playing up? It's like a greenhouse in here."<</speech>>
<<speech "$name">>"It's been on the blink for weeks."<</speech>>
<<speech "Jane">>"Get it looked at. That's the second house today."<</speech>>
<<case "Cousin's House">>
Officer Jane knocks politely and steps into the hallway. Winter is still flushed and dishevelled, skirt slightly crooked, a visible trail of cum running slowly down the inside of her thigh — and she is standing very deliberately still so as not to draw the eye to it.
<<speech "Jane">>"Sorry to bother you. Just doing the rounds. We've had reports about noise, and about people acting off. You seen anything unusual round here?"<</speech>>
Winter straightens up despite the shake in her legs, and gives you one quick submissive glance before she answers.
<<speech "Winter">>(sharp and efficient, but huskier than she'd like) "Nothing out of the ordinary, Officer."<</speech>>
<<speech "Jane">>"You'd be the one to notice, that's why I ask."<</speech>>
<<speech "Winter">>"There's nothing to notice."<</speech>>
<<speech "$name">>"What sort of reports?"<</speech>>
<<speech "Jane">>"Vague ones. That's the trouble with them."<</speech>>
<<speech "Jane">>(pushing her hair off her forehead) "Everyone tells me somebody isn't themselves and nobody can say what they mean by it. Twenty-odd calls and not one thing I can write down."<</speech>>
<<speech "$name">>"Sounds like a wasted month."<</speech>>
<<speech "Jane">>"It's shaping up that way."<</speech>>
She takes another look at Winter — the flush, the unsteadiness, the way she hasn't moved an inch since the door opened.
<<speech "Jane">>"You alright? You look like you're coming down with something."<</speech>>
<<speech "Winter">>"I'm fine."<</speech>>
<<speech "Jane">>"Take it easy anyway. There's a lot of it about."<</speech>>
She lets herself out. Winter exhales shakily and presses her thighs together as another wave of it rolls through her, and doesn't move until the car has pulled away.
<<case "Eva's House">>
/* Angel (Agent) inspecting Eva (Resident) - Req 50 */
The knock comes just as Eva pulls her mouth off your cock, a thin string of saliva still connecting her lips to the tip. She wipes her mouth on the back of her wrist, gets to her feet, and opens the door with her brightest smile already loaded.
Detective Angel is on the step with a folder she's clearly been carrying all day.
<<speech "Eva">>(bright, though her voice is wrecked and her knees aren't steady) "Detective. What brings you here?"<</speech>>
<<speech "Angel">>"Another report. Strange behaviour, people acting out of character. I'm doing the whole road."<</speech>>
Her sharp gaze goes over Eva's flushed face and swollen lips, and the way she's drifted back to stand almost against you.
<<speech "Angel">>"You look like you've just run a marathon."<</speech>>
<<speech "Eva">>(a laugh, a touch too breathy) "Just catching up with my best friend. You know how it is."<</speech>>
She leans into your side, one hand resting on your chest as though it belongs there. Under the charm there's something else in the glance she gives you.
<<speech "$name">>"What do the reports actually say, out of interest?"<</speech>>
<<speech "Angel">>"Not much. That's the problem."<</speech>>
<<speech "Angel">>(flat, honest) "Nobody's hurt, nothing's stolen, nobody's complained about anything. It's families ringing to say somebody's changed. Twenty-two of them now, and there's no crime in any of it."<</speech>>
<<speech "Eva">>"So why keep coming round?"<</speech>>
<<speech "Angel">>"Because twenty-two is a number, and numbers usually have a reason underneath them."<</speech>>
Eva shifts her thighs together, visibly fighting the urge to go back down on her knees. Angel does not miss it — you watch her see it, and watch her decide she has no idea what to do with it.
<<speech "Angel">>"Anything comes to mind, either of you, the station'll take it."<</speech>>
She looks at Eva's hand on your chest for a moment longer.
<<speech "Angel">>"…Enjoy your afternoon."<</speech>>
<<case "Mansion">>
/* Ember (Agent) inspecting Luna (Resident) - Req 75 */
Chief Ember comes into the opulent sitting room a minute after you've finished inside Luna. The widow is still flushed and breathing unsteadily, though she gathers herself with her usual quiet dignity, smoothing down her expensive dress. It doesn't hide the tremble in her legs or the faint wet trail on her inner thigh.
<<speech "Luna">>(soft, reserved, faintly breathy) "Chief Ember."<</speech>>
<<speech "Ember">>"Ma'am. I'm asking the same eight questions in thirty houses and I've twelve left, so I'll be brief."<</speech>>
Her pragmatic stare settles on Luna and hardens slightly.
<<speech "Ember">>"You're looking unwell."<</speech>>
<<speech "Luna">>"I assure you I'm perfectly well."<</speech>>
<<speech "Ember">>"Mm."<</speech>>
She turns her head towards you, unhurried.
<<speech "Ember">>"And you keep turning up wherever these incidents are. Not near them. In them."<</speech>>
<<speech "$name">>"She's been on her own in this house for years, Chief. Somebody finally visits and that's an incident?"<</speech>>
<<speech "Ember">>(without heat) "No. It's a coincidence, and I've a list of them, and none of it amounts to anything I can act on."<</speech>>
Luna folds her hands in front of her, the picture of refined loneliness — except for the way she keeps glancing at you with barely concealed hunger.
<<speech "Luna">>"$name has been wonderful company lately. He makes me feel… taken care of."<</speech>>
The last of it comes out almost as a quiet moan. She stares at the fireplace afterwards.
Ember crosses her arms. The room is heavy and close and musky, and it's plainly bothering her — she keeps not quite settling.
<<speech "Ember">>"Is your heating on, ma'am? It's very warm in here."<</speech>>
<<speech "Luna">>"The house holds it."<</speech>>
<<speech "Ember">>"Right."<</speech>>
<<speech "Ember">>(at the door, more to the room than to either of you) "I don't know what's going on in this town. Twenty-two years and I've always at least been able to say what a thing //is//."<</speech>>
<<case "Sorority House">>
Nancy answers the sorority house door herself, which she never does. She's trying hard to look composed and not quite getting there — hair messy, blouse buttoned unevenly, cheeks deeply flushed, a faint sheen of sweat across her neck and collarbone. She stands with her thighs pressed tightly together.
<<speech "Angel">>"Miss Nancy. Sorry to bother you. I wanted to ask whether you've noticed any of your students acting strangely. Unusual behaviour, mood swings, that sort of thing."<</speech>>
<<speech "Nancy">>(polished, president's voice, breathing slightly laboured) "Of course, Detective. I take the wellbeing of my girls very seriously. I haven't noticed anything unusual. Everything's been normal."<</speech>>
As she says it a slow trickle of cum runs down the inside of her thigh. She shifts her weight to cover it, and the movement is what draws the eye, and she keeps glancing at you with a quiet, submissive need that undoes the whole performance. Her body is plainly still riding the aftershocks of being fucked.
<<speech "$name">>"Is it just this house you're asking, or everywhere?"<</speech>>
<<speech "Angel">>"Everywhere. Six of the names on my list live here, so it's a bigger cluster than most — but I've been at this a fortnight and I've got nothing on any of them."<</speech>>
<<speech "Nancy">>"Six?"<</speech>>
<<speech "Angel">>"Nobody's in trouble. Genuinely. It's relatives ringing in, not complaints."<</speech>>
Nancy's chin lifts. Being handed a number about her own house that she didn't already have visibly stings more than the question did.
<<speech "Nancy">>"I'd know if something were wrong here."<</speech>>
<<speech "Angel">>"I'm sure."<</speech>>
Angel's eyes narrow slightly. She keeps her voice entirely professional.
<<speech "Angel">>"Thank you. I'll be in touch if I need anything else."<</speech>>
<<case "Dormitory Hall">>
Detective Angel turns into the dormitory hallway and stops short.
Myra is against the wall looking thoroughly dishevelled — earbuds dangling, hair a mess, lips swollen and glossy. Melody is standing close beside you, flushed and breathing softly, clothes rumpled, one strap of her top slipping off her shoulder.
Four doors are open along the corridor. Nobody comes out.
Angel takes it all in carefully, suspicion clear but controlled.
<<speech "Angel">>"Evening. I'm looking into some odd reports round campus. Either of you noticed anyone acting different lately?"<</speech>>
Myra shrugs with her usual chill, though her voice is hoarse and her thighs keep shifting.
<<speech "Myra">>"Nah. Nothing weird that I've seen."<</speech>>
She wipes the corner of her mouth discreetly with the back of her hand as she says it. Angel's eyes go to the movement and stay there half a second.
Melody stays pressed lightly against your side, cheeks burning, eyes glassy with lingering arousal.
<<speech "Melody">>(soft, doing her best to sound normal) "I haven't noticed anything either. Everyone seems fine."<</speech>>
Her fingers tighten in your shirt without her noticing and her legs are trembling.
<<speech "$name">>"What sort of reports?"<</speech>>
<<speech "Angel">>"Students not turning up. Not answering their families. Wearing things they'd never have worn a month ago."<</speech>>
<<speech "Angel">>(a tired shrug) "And every one of them tells me she's fine and means it. That's the bit I can't get past."<</speech>>
Her gaze lingers on the state of them both, and on how close they're standing to you.
<<speech "Angel">>"Alright. Let me know if anything comes to mind."<</speech>>
She walks the length of the corridor on her way out, past every open door, and not one of them so much as looks up.
<</switch>>
</div>
<<include "SuspicionScene-Footer">>
</div><<nobr>>
<<set _loc = $sceneLocation>>
<<set _agent = $activeSuspicionAgent>>
<<set _res = $activeSuspicionResidents>>
<<set _id = $activeSceneID>>
<</nobr>>
<div class="suspicion-scene-wrap">
<div class="narrative-box">
/* ── CAST STRIP ──────────────────────────────────────────────────────────
Sized to match LocationScene-Header: fluid tiles that divide the row,
min 100px / max 200px, rather than the old fixed 150x198.
The agent is drawn whether or not she has been MET. All three suspicion
agents (Angel, Jane, Ember) start met:false, so gating her tile on .met
meant the investigating officer had no portrait in the majority of
scenes — including every two-girl scene, which is most of them.
─────────────────────────────────────────────────────────────────────── */
<<set _agentC = $activeSuspicionAgent ? State.variables[$activeSuspicionAgent] : null>>
<div style="display:flex; gap:12px; justify-content:center; align-items:flex-end; flex-wrap:wrap; margin-bottom:24px;">
<<if _agentC>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getEventImagePath(_agentC.name)" style="width:100%; border-radius:8px; border:2px solid #ff4444; display:block;">
<div style="color:#ff4444; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _agentC.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Investigating</div>
</div>
<</if>>
<<if $sceneGroup and $sceneGroup.length > 0>>
<<for _pgid range $sceneGroup>>
<<set _pgc = State.variables[_pgid]>>
<<if _pgc and _pgc.met>>
<<capture _pgid>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getEventImagePath(_pgc.name)" style="width:100%; border-radius:8px; border:2px solid #9933cc; display:block;">
<div style="color:#cc88ff; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _pgc.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Corr: <<print _pgc.corr>>%</div>
</div>
<</capture>>
<</if>>
<</for>>
<</if>>
</div>
<<switch _id>>
<<case "School Hallway">>
Detective Angel is in the corridor for the third time this week, waiting on a meeting with the head that keeps getting pushed back. She's leaning against the lockers with a coffee she hasn't touched.
The girls' bathroom door swings open and Violet comes out. Her stylish outfit has been swapped for a tight crop top that barely contains her breasts and a short pleated skirt that threatens to flash the corridor with every step. Her hair is a mess, her cheeks are flushed, and her thighs glisten wetly under the hem.
You come out three seconds after her, still tucking yourself away.
The corridor is packed. Nobody looks up.
Angel does. Her eyes go to the outfit first, then to the bathroom door, then to you, and she straightens off the lockers.
<<speech "Angel">>"Morning."<</speech>>
<<speech "Violet">>(flipping her hair, breathier than she means) "Morning, Detective."<</speech>>
<<speech "Angel">>"Wrong bathroom, that one."<</speech>>
<<speech "$name">>"The other one's out of order."<</speech>>
<<speech "Angel">>"Mm."<</speech>>
She lets it go — because what else is it, a boy in the wrong toilets — and asks the thing she's been asking all week instead.
<<speech "Angel">>"Since you're both here. Noticed anyone round the school behaving oddly lately?"<</speech>>
<<speech "Violet">>"Oddly how?"<</speech>>
<<speech "Angel">>"Out of character. Not themselves."<</speech>>
<<speech "Angel">>(she shrugs, aware how thin it sounds) "That's genuinely all I've got. Everyone keeps saying it and nobody can be more specific."<</speech>>
<<speech "Violet">>"Not that I've noticed."<</speech>>
Violet shifts her legs as another wave of it rolls through her, biting her lip, and a slow bead of cum slides down between her massive tits and disappears under the tiny top. She gives you a quick, needy glance while she does it.
Angel's gaze tracks the outfit for a second longer than she means it to. Then she looks at the ceiling, faintly annoyed with herself, and rubs her eyes.
<<speech "Angel">>"God, this corridor's warm. Is the heating stuck on in here?"<</speech>>
<<speech "$name">>"It's been like that all term."<</speech>>
<<speech "Angel">>"Right."<</speech>>
<<speech "Angel">>(to Violet, already turning away) "Get to your lesson. And put a jumper on, you'll freeze."<</speech>>
<<case "School Rooftop">>
The roof door bangs open and Detective Angel is on the other side of it, checking whether it opens from both sides, and she finds the three of you up here.
Abella is against the railing in tight athletic shorts that have ridden up into her ass and a sports bra. Caprice is beside you in an oversized sweater that barely covers her hips with nothing at all underneath it. Abella's face is flushed and her legs aren't steady. Caprice's breathing hasn't come back down.
<<speech "Angel">>"…This is supposed to be alarmed."<</speech>>
<<speech "Abella">>(arms crossed under her chest, trying for tough) "It's just the roof."<</speech>>
<<speech "Angel">>"It's a fire exit is what it is. Turns out it opens from both sides, which is the opposite of what I was told."<</speech>>
<<speech "Caprice">>(dry) "So we're not in trouble."<</speech>>
<<speech "Angel">>"You're on a roof. I'd rather you weren't."<</speech>>
<<speech "Angel">>(propping it with her foot) "While I'm up here — either of you noticed anyone acting strangely round the school? Students, staff, anyone."<</speech>>
<<speech "Abella">>"No."<</speech>>
<<speech "Caprice">>"Nope."<</speech>>
<<speech "Angel">>"Worth a try. That's about thirty people who've said that."<</speech>>
Caprice presses her thighs together — she's still dripping down the inside of one of them, and the sweater isn't long enough to hide it. Abella keeps glancing at you, submissive and hungry, and forgetting to look tough while she does it.
Angel takes in the state of them both: six floors up in a cold wind, one in a sports bra and the other in a jumper and nothing else.
<<speech "Angel">>"You're not cold?"<</speech>>
<<speech "Caprice">>"Not really."<</speech>>
<<speech "Angel">>(a pause) "Right."<</speech>>
<<speech "$name">>"What's the strange behaviour thing about?"<</speech>>
<<speech "Angel">>"Parents ringing the station about their kids. Kids ringing about their mums. Nobody's hurt, nothing's been taken, so there's nothing to open."<</speech>>
<<speech "Angel">>(a flat, tired smile) "I'm essentially being paid to walk around looking at people this month."<</speech>>
She goes down first and holds the door until you all follow.
<<case "Staff Room">>
Officer Jane is in the school to talk to the sixth form about road safety and she's twenty minutes early, so she's come to find a cup of tea.
Veruca and Anya are both in the staff room with you. Veruca — normally the most covered-up woman in the building — is in a noticeably short skirt and a blouse pulled too tight across the front. Anya's in low-cut and tight jeans. Both of them look freshly fucked: flushed faces, messy hair, legs that won't quite hold still.
<<speech "Jane">>"Sorry — alright if I sit in here till half past?"<</speech>>
<<speech "Veruca">>(soft, unsteady) "Of course."<</speech>>
<<speech "Jane">>"Cheers."<</speech>>
She gets about four seconds into her tea before she takes the room in properly, and you watch her decide not to make anything of it.
<<speech "Jane">>"Can I ask you two something daft? You see these kids every day."<</speech>>
<<speech "Anya">>"Go on."<</speech>>
<<speech "Jane">>"Noticed any of them behaving unlike themselves? Last month or so."<</speech>>
<<speech "Veruca">>"…Not really."<</speech>>
She keeps her hands clasped in front of her to hide how badly they're shaking.
<<speech "Anya">>"Nothing that stands out."<</speech>>
Anya folds her arms and tries to sound like herself and doesn't manage it. She shifts her weight, and the wet patch spreading through the denim at the top of her thighs shifts with her. She steals a glance at you and it isn't a teacher's glance.
<<speech "Jane">>"Fair enough. We've had a lot of calls and none of them go anywhere."<</speech>>
<<speech "Jane">>(both hands round the mug) "The parents all use the same phrase, that's the bit that gets me. 'She's not herself.' Word for word, twenty-odd times."<</speech>>
<<speech "$name">>"Could be people copying each other. Someone says it, it spreads."<</speech>>
<<speech "Jane">>(pointing at you with the mug) "See, that's the most sensible thing anyone's said to me all week. I'll take it."<</speech>>
She goes to drink and then doesn't, looking at the mug instead of into it, and her collar is already open.
<<speech "Jane">>"Is that radiator on full? It's like a sauna in here."<</speech>>
<<speech "Veruca">>"It's been broken since term started."<</speech>>
<<speech "Jane">>"Get it logged. Second staff room this week."<</speech>>
She puts the mug down half-finished and stands up a good ten minutes earlier than she needs to.
<<speech "Jane">>"Right — I'll go and find the hall. Thanks, ladies."<</speech>>
<<case "Student Council">>
Chief Ember has come to drop off the road-closure paperwork for the street fair, which is a two-minute errand a constable could have run. She opens the council office door without knocking, because in twenty-two years nobody has ever needed her to knock on a student council office.
Carolina is bent over the large desk with her skirt hiked up, moaning softly as you thrust into her from behind. Adria is standing three feet away in her skimpy council uniform, flushed and breathing hard, one hand working between her own thighs.
Nobody stops.
<<speech "Ember">>(after a long moment) "…The permits."<</speech>>
She puts them on a chair, because the desk is occupied.
<<speech "Carolina">>(gripping the edge, breathless) "Thanks, Chief."<</speech>>
<<speech "Carolina">>(barely suppressing a moan as you push deeper) "Just — handling some council business."<</speech>>
<<speech "Ember">>"Mm."<</speech>>
She doesn't leave. In twenty-two years she has walked in on a great many things and always known instantly what she was looking at and what to do about it, and this is three adults, no complaint, no offence she can name, and not one of them embarrassed about being caught fucking at school.
Carolina pushes back onto you and barely muffles it. Adria straightens up and forces the president's voice out of a wrecked throat.
<<speech "Adria">>"Was there anything else?"<</speech>>
<<speech "Ember">>"Miss Adria. Your hand."<</speech>>
Adria looks down at it. She looks for a long moment — genuinely puzzled, the way you'd look at somebody else's hand — and then puts it back where it was and carries on.
Something in Ember's face changes.
<<speech "$name">>"You could knock, Chief."<</speech>>
<<speech "Ember">>(quietly) "I did. Twice. You didn't hear me. Neither did they."<</speech>>
<<speech "Ember">>(stepping back into the corridor) "Signed by Friday, please."<</speech>>
The door pulls to. Her footsteps don't start for a few seconds.
The moment they do, Carolina moans loudly and shoves herself back onto your cock, and Adria drops to her knees to join in.
<<case "Cafeteria">>
Detective Angel comes into the cafeteria for a coffee, because the machine at the station has been broken a fortnight and this one is forty seconds from the car park.
Natalie is on her knees behind a table with her lips wrapped around your cock, sucking with the same focused intensity she gives her thesis. Karlee stands beside you with a hand resting on your shoulder, skimpy top, skin flushed, doing her level best to look pragmatic and in charge.
The cafeteria is not empty. Forty people are eating lunch fifteen feet away with their eyes on their trays.
Angel gets three steps in and stops.
<<speech "Angel">>"…Is nobody going to say anything?"<</speech>>
A boy at the next table turns a page.
<<speech "Karlee">>(steady) "Everything's under control, Detective."<</speech>>
<<speech "Angel">>"Under control."<</speech>>
<<speech "Karlee">>"No chaos I can't handle."<</speech>>
Her hand tightens on your shoulder and her thighs press together as she watches Natalie work.
Natalie pulls off your cock with a wet pop, strings of saliva still connecting her lips to your shaft, and answers as though she's been asked about her reading.
<<speech "Natalie">>"Was there something you needed?"<</speech>>
She leans back in and takes you deep again. Angel's jaw sets. She doesn't look angry — she looks slightly ill.
<<speech "$name">>"You're the only one making a thing of it."<</speech>>
<<speech "Angel">>(and she does look round again, at forty students not looking up) "Yeah. I'd noticed."<</speech>>
<<speech "Angel">>(more to herself than to you) "That's the part I can't write down. Not what's happening at this table — that nobody in this room thinks anything is."<</speech>>
She walks out without the coffee. Through the window you can see her stop in the car park, stand a moment with one hand flat on the roof of her car, and then get in.
<<case "Cheerleader Track">>
Officer Jane is at the school for the under-twelves' fun run on the next field, in a hi-vis and holding a clipboard she hasn't written on. The cheer track runs alongside it, which is the only reason she comes over.
You're standing with Lacy and Blake. Their cheer uniforms have been modified into micro-skirts that barely cover their asses and crop tops so small their underboobs show with every movement.
<<speech "Jane">>"Ladies. I'm going to have to say something about the kit, sorry."<</speech>>
<<speech "Lacy">>(smirking, flipping her hair) "What's the matter, Officer? Too much skin for you?"<</speech>>
<<speech "Jane">>"For me, nothing. For the parents on that touchline, apparently loads."<</speech>>
<<speech "Jane">>(apologetic) "That's the whole complaint. I've just been sent over."<</speech>>
The smirk stalls. There's nothing to push against.
<<speech "Lacy">>"So we'll move down the far end."<</speech>>
<<speech "Jane">>"That'd do it. Cheers."<</speech>>
She should go. She doesn't, quite — she's looking at Blake, who hasn't said a word and is watching you instead of the conversation.
<<speech "Jane">>"Blake, isn't it? You alright?"<</speech>>
<<speech "Blake">>(soft, slow) "I'm fine."<</speech>>
<<speech "Jane">>(a beat) "Your mum's friend runs with me on Sundays. She was asking after you."<</speech>>
Blake blinks a few times, as though the sentence has to travel a long way, and her eyes come back to you before they come back to Jane.
<<speech "$name">>"She's been flat out with training."<</speech>>
<<speech "Jane">>"Course. Competitions coming up, I expect."<</speech>>
<<speech "Jane">>(tapping the clipboard against her leg, twice, unsatisfied) "Far end, then. Thanks, ladies."<</speech>>
She heads back to the fun run.
The second she's gone the two of them drag you behind the bleachers. Lacy turns on Blake with a challenging grin.
<<speech "Lacy">>"Come on Blake, be real with me. Are you actually a lesbian, or just a slut that craves cock?"<</speech>>
<<speech "Blake">>(blushing, dry, eyes flicking to you with open hunger) "I like what feels good."<</speech>>
<<speech "Lacy">>(shoving her aside) "Watch how a real bitch takes it."<</speech>>
She hikes up her pathetic excuse for a skirt and slams herself down onto your cock, riding you like a depraved whore, moaning shamelessly as her tight pussy squeezes you. Blake watches with lust-blown eyes before taking her turn, sucking your cock clean of Lacy's juices with affectionate, sloppy devotion. The two of them compete nastily — Lacy riding you hard and fast, Blake trying to outdo her with wet, gagging blowjobs — both of them dripping and addicted to your cum, forty feet from a field full of parents.
<<case "School Pool">>
Detective Angel is walking the perimeter of the building because the head asked her to look at the fire exits, and the pool doors are on her list.
She pushes through them and stops dead.
The entire swim session has gone. Harley and Ariana are in the sluttiest micro-bikinis imaginable — thin strings that barely cover their nipples and pussies. Several students react openly: a boy in the shallow end whistles, a girl on the bleachers stares with her hand over her mouth.
Harley spots her first. She swims to the edge and hauls herself out, water running off her barely-covered body, and gets to Angel before Angel gets anywhere.
<<speech "Harley">>"Detective Angel! Are you here to watch?"<</speech>>
<<speech "Angel">>"I'm here to look at a door."<</speech>>
<<speech "Angel">>(glancing round) "Where's your coach?"<</speech>>
<<speech "Harley">>(a beat too long) "…She's about somewhere."<</speech>>
<<speech "Angel">>"There's twenty of you in a pool and a diving board in use. Somebody should be down that end with a whistle."<</speech>>
<<speech "Harley">>"I'll go and find her!"<</speech>>
She does not go and find her. She plants herself squarely between Angel and the changing room door and starts asking about the police fitness test, leaning in so her tits nearly spill out, stretching in ways that aren't remotely innocent.
Behind her, Ariana takes your hand and silently pulls you into the changing room.
The door shuts. The stoic swimmer turns round and there's nothing disciplined left in her.
<<speech "Ariana">>(bending over a bench, spreading her ass) "Fuck me."<</speech>>
<<speech "Ariana">>(quiet, begging) "I need your cock ruining my pussy again. Please…"<</speech>>
You slam into her soaked cunt hard, pounding her trained body until she's biting down on her own forearm to stay quiet, her tight walls milking you desperately. Through the door you can hear Harley's voice pitched high and cheerful and Angel's underneath it, patient and going nowhere — //is there an adult in this building, love// — and Harley talking straight over the top of her.
Ariana cums hard around your cock, shaking, arm still in her teeth, and you empty yourself into her while the conversation carries on four feet away.
By the time the outside door finally bangs, Ariana is a cum-drenched mess leaking down her thighs on the bench. Harley comes in a minute later, flushed and pleased with herself, already pulling the string on her top.
<<speech "Harley">>"She's gone to find the caretaker."<</speech>>
<<speech "Harley">>(climbing onto you both) "That'll take ages."<</speech>>
<</switch>>
</div>
<<include "SuspicionScene-Footer">>
</div><<nobr>>
<<set _loc = $sceneLocation>>
<<set _agent = $activeSuspicionAgent>>
<<set _res = $activeSuspicionResidents>>
<<set _id = $activeSceneID>>
<</nobr>>
<div class="suspicion-scene-wrap">
<div class="narrative-box">
/* ── CAST STRIP ──────────────────────────────────────────────────────────
Sized to match LocationScene-Header: fluid tiles that divide the row,
min 100px / max 200px, rather than the old fixed 150x198.
The agent is drawn whether or not she has been MET. All three suspicion
agents (Angel, Jane, Ember) start met:false, so gating her tile on .met
meant the investigating officer had no portrait in the majority of
scenes — including every two-girl scene, which is most of them.
─────────────────────────────────────────────────────────────────────── */
<<set _agentC = $activeSuspicionAgent ? State.variables[$activeSuspicionAgent] : null>>
<div style="display:flex; gap:12px; justify-content:center; align-items:flex-end; flex-wrap:wrap; margin-bottom:24px;">
<<if _agentC>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getEventImagePath(_agentC.name)" style="width:100%; border-radius:8px; border:2px solid #ff4444; display:block;">
<div style="color:#ff4444; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _agentC.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Investigating</div>
</div>
<</if>>
<<if $sceneGroup and $sceneGroup.length > 0>>
<<for _pgid range $sceneGroup>>
<<set _pgc = State.variables[_pgid]>>
<<if _pgc and _pgc.met>>
<<capture _pgid>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getEventImagePath(_pgc.name)" style="width:100%; border-radius:8px; border:2px solid #9933cc; display:block;">
<div style="color:#cc88ff; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _pgc.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Corr: <<print _pgc.corr>>%</div>
</div>
<</capture>>
<</if>>
<</for>>
<</if>>
</div>
<<switch _id>>
<<case "Town Square">>
Officer Jane is doing her usual rounds through the busy square when she spots the three of you.
Kailey is in an extremely short sundress with no bra, her hard nipples clearly visible through it. Vina is in a tiny crop top and a micro-skirt that flashes her ass with every breeze. The square is full of people and not one of them is looking directly at either girl.
Jane comes over. She's smiling, but the eyebrow goes up.
<<speech "Jane">>"Hey, you three. Those outfits are bold today."<</speech>>
<<speech "Kailey">>(bright, cheerful, thighs glistening) "We're just enjoying the nice weather, Officer Jane!"<</speech>>
<<speech "Jane">>"It's freezing, love."<</speech>>
Kailey looks down at herself with a small delay, as though the information is arriving from somewhere far off.
<<speech "Jane">>"Anyway. Everything alright round here? I've been hearing some strange stories lately."<</speech>>
<<speech "Vina">>(easy, laughing it off) "Nothing weird going on. Just out with $name."<</speech>>
<<speech "$name">>"What kind of stories?"<</speech>>
<<speech "Jane">>"Public order calls, mostly. I'd normally get two a month and I've had eleven."<</speech>>
<<speech "Jane">>(uncomfortable) "And when we turn up they're not drunk and they're not on anything. They're just not bothered. That's the word the sergeant keeps writing down. Not bothered."<</speech>>
<<speech "Kailey">>"That doesn't sound so bad."<</speech>>
<<speech "Jane">>(looking at her a moment too long) "…No. I suppose it doesn't."<</speech>>
She shrugs out of her jacket and puts it round Kailey's shoulders, businesslike, no comment on it.
<<speech "Jane">>"Keep hold of that. Drop it at the station whenever. And if anything occurs to you — anything that's changed round here — tell me. I'd love this to be something boring."<</speech>>
She heads off across the square with a wave.
Ten minutes later Kailey and Vina drag you behind a secluded cluster of trees at the edge of it. Kailey drops to her knees first and sucks your cock like a greedy slut, still wearing the jacket, while Vina makes out with you and whispers filthy encouragement in your ear. They take turns slobbering over your dick, both of them behaving like depraved cum-hungry bitches with the footpath thirty feet away, and Kailey doesn't take the jacket off once.
<<case "Hotel">>
Detective Angel comes into the hotel lobby and finds Caitlyn behind the front desk. The usually put-together girl is in a tiny skirt that barely covers her ass and a tight blouse with half the buttons undone, showing off her cleavage and the dried cum stains across her chest.
Caitlyn holds the bored professional smile. Her voice comes out husky and her legs aren't steady.
<<speech "Angel">>"Miss Caitlyn. Following up on some unusual reports in the area. Any strange guests? Anything odd going on here at all?"<</speech>>
<<speech "Caitlyn">>(squeezing her thighs together) "Everything's normal here, Detective. $name was just helping me reorganise some things in the back."<</speech>>
Angel looks you both up and down. There's suspicion in it, but it's the tired sort — she's had this exact conversation a dozen times this fortnight.
<<speech "$name">>"Is there something we should be watching for?"<</speech>>
<<speech "Angel">>"If I knew that I'd have written it on a poster by now."<</speech>>
<<speech "Angel">>(leaning on the counter, then straightening off it again, frowning) "It's people changing. That's all any of it comes to. No crime, no complaint, no victim. I'm chasing a pattern and it's making me look mad, so I'm doing the boring version — guest books, receipts, everywhere, until something lines up."<</speech>>
<<speech "Caitlyn">>"Do you want the book?"<</speech>>
<<speech "Angel">>"Please."<</speech>>
She reads it for a while and finds four regulars and nothing else. She frowns at the room rather than the page.
<<speech "Angel">>"Is your air conditioning off? It's stifling in here."<</speech>>
<<speech "Caitlyn">>"It's on."<</speech>>
<<speech "Angel">>"Hm."<</speech>>
She leaves visibly unconvinced and with nothing to be unconvinced about. The moment the door swings shut Caitlyn pulls you into the staff bathroom, bends over the sink and yanks her tiny skirt up.
<<speech "Caitlyn">>(desperate) "Fuck me hard. I need your cock stretching my slutty pussy again."<</speech>>
You pound her roughly over the basin, her palms squeaking on the mirror, and she moans like a whore loud enough to carry out into the lobby. She cums hard, legs shaking under her, your cum dripping down her thighs onto the tile.
<<case "Park">>
Officer Jane is walking through the park when she sees you with Maya and Casey. Maya's in a tiny tank top and micro-shorts riding up into her ass; Casey's in something expensive and extremely revealing. Jane changes course and comes over, and she's smiling, because she likes Maya.
<<speech "Jane">>"Those are some daring outfits for the park, ladies."<</speech>>
<<speech "Maya">>(warm, cheerful, nipples visibly hard) "We're just enjoying the sunshine!"<</speech>>
<<speech "Jane">>"How's your mum's hip?"<</speech>>
<<speech "Maya">>(automatic) "She's good!"<</speech>>
<<speech "Jane">>"Good. Tell her I'll pop round."<</speech>>
<<speech "Jane">>(beat) "You been up to see her?"<</speech>>
<<speech "Maya">>"…Course."<</speech>>
Jane's smile holds, but something behind it adjusts. She was at the hospital on Monday. She doesn't say so.
<<speech "Casey">>(arms crossed under her tits, cold) "Nothing strange here, Officer."<</speech>>
<<speech "Jane">>"I hadn't asked yet."<</speech>>
<<speech "Casey">>"You were going to."<</speech>>
<<speech "Jane">>(holding her hands up) "Fair enough. I've been hearing odd rumours and I'm asking everybody. That's the whole of it."<</speech>>
<<speech "$name">>"People change, Officer."<</speech>>
<<speech "Jane">>"They do. Slowly, though, and one at a time."<</speech>>
<<speech "Jane">>(a tired shrug) "Not twenty of them at once. That's all I've got — twenty people and a feeling. My sergeant reckons it's the weather."<</speech>>
Casey's voice wavers when she answers, barely holding the lust down, and Maya keeps giving you small submissive glances while Jane is still talking.
<<speech "Jane">>(to Maya, gently, before she goes) "Go and see your mum. Today. That's not police advice."<</speech>>
She leaves with a friendly warning to behave.
Two minutes later Maya has forgotten the hospital entirely and the pair of them pull you deeper into the trees. Maya drops to her knees and starts sucking you sloppily while Casey watches with a sneer before shoving in beside her. The two of them turn into nasty, competing cumsluts — Maya deepthroating you eagerly, Casey demanding you fuck her face instead, both of them dripping wet and thoroughly addicted.
<<case "Beach">>
Officer Jane is patrolling near the beach when she spots you with Uma and Rae, who have obviously skipped class. Both girls are in the sluttiest bikinis available — strings that barely cover their nipples and pussies and leave nothing whatever to the imagination.
<<speech "Jane">>"Skipping, are we? Adriana rang the station about it, and she's never done that in nine years."<</speech>>
<<speech "Uma">>(striking a pose, performing) "We're just practising our performance art, Officer!"<</speech>>
<<speech "Rae">>(smirking) "Relax. We're not causing trouble… much."<</speech>>
<<speech "Jane">>"You're not, no. That's not really why I came down."<</speech>>
She looks out at the water rather than at them.
<<speech "Jane">>"She didn't ring about the truancy. She rang because she said you weren't yourselves, and she was upset about it, and I didn't know what to put in the log."<</speech>>
<<speech "Rae">>"We're fine."<</speech>>
<<speech "Jane">>"Everyone's fine. Nineteen conversations and everyone's fine."<</speech>>
Uma's body is flushed and trembling with need under the performance. Rae's eyes are glassy with it and the smirk has gone fixed, like something left out in the sun.
<<speech "$name">>"We are adults. We can skip a class, it's not mandatory."<</speech>>
<<speech "Jane">>"You can."<</speech>>
<<speech "Jane">>(wiping her forehead) "God, it's warm out. Or it's me."<</speech>>
She heads back up the beach with a joking warning, and stops once to look back at the three of you.
As soon as she's over the dune Uma drags you behind the rocks and bends over, pulling her bikini aside.
<<speech "Uma">>"Fuck my tight cunt in public, $name. I want everyone to see what a whore I've become."<</speech>>
Rae shoves her face between your legs and sucks your balls while you pound Uma senseless against the rock. The two of them turn into loud, depraved sluts, moaning shamelessly and taking turns getting filled and covered in your cum, loud enough to turn heads on the path above and not caring in the slightest.
<<case "Town Hall">>
Chief Ember comes into the Town Hall and finds Lily at the front desk. The usually bubbly secretary is dressed like a complete office slut — tiny pencil skirt, sheer blouse with no bra underneath, heels that make her legs look obscene.
<<speech "Ember">>"Miss Lily. I need to speak with Nicole about some concerning reports. Unusual behaviour in town. Have you noticed anything strange?"<</speech>>
<<speech "Lily">>(bright, cheerful, her voice cracking slightly) "Oh, everything's been perfectly normal here, Chief Ember! We've had the usual reports, but this town's always been pretty peaceful."<</speech>>
Her thighs are visibly slick below the hem of the skirt. She keeps smiling.
<<speech "Ember">>"Mm."<</speech>>
She looks at the appointment diary on the desk, then at Lily, then at the diary again.
<<speech "Ember">>"There are four appointments in this book and two of them are for last Tuesday. You've run this desk three years without an error."<</speech>>
<<speech "Lily">>"I'll fix it right away!"<</speech>>
<<speech "$name">>"She's been under a lot of pressure lately."<</speech>>
<<speech "Ember">>(mildly, without turning) "Everyone has, apparently. Ninth person this week to be under a lot of pressure and perfectly fine at the same time. I'm starting to hope it's something going round. A virus, a bad batch of something, carbon monoxide in a building we all use. I'd take any of those — I could hand it to the health authority and go back to proper work."<</speech>>
<<speech "Lily">>"That does sound worrying!"<</speech>>
<<speech "Ember">>"It's the most hopeful thing I've said all week."<</speech>>
She studies Lily a moment longer, then nods and leaves.
The second she's gone Lily locks the door, hikes the tiny skirt up and bends over her own desk across the open diary, spreading her ass.
<<speech "Lily">>(shameless) "Please fuck me. I've been such a needy little whore all day waiting for you."<</speech>>
You rail her hard over the desk, her cheek against the appointment book, and the sweet secretary comes apart into a drooling, cock-drunk mess, cumming repeatedly with ink smudging across her face — and when it's over she pulls the skirt down and sits back at the desk exactly as she was.
<</switch>>
</div>
<<include "SuspicionScene-Footer">>
</div><<nobr>>
<<set _loc = $sceneLocation>>
<<set _agent = $activeSuspicionAgent>>
<<set _res = $activeSuspicionResidents>>
<<set _id = $activeSceneID>>
<</nobr>>
<div class="suspicion-scene-wrap">
<div class="narrative-box">
/* ── CAST STRIP ──────────────────────────────────────────────────────────
Sized to match LocationScene-Header: fluid tiles that divide the row,
min 100px / max 200px, rather than the old fixed 150x198.
The agent is drawn whether or not she has been MET. All three suspicion
agents (Angel, Jane, Ember) start met:false, so gating her tile on .met
meant the investigating officer had no portrait in the majority of
scenes — including every two-girl scene, which is most of them.
─────────────────────────────────────────────────────────────────────── */
<<set _agentC = $activeSuspicionAgent ? State.variables[$activeSuspicionAgent] : null>>
<div style="display:flex; gap:12px; justify-content:center; align-items:flex-end; flex-wrap:wrap; margin-bottom:24px;">
<<if _agentC>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getEventImagePath(_agentC.name)" style="width:100%; border-radius:8px; border:2px solid #ff4444; display:block;">
<div style="color:#ff4444; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _agentC.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Investigating</div>
</div>
<</if>>
<<if $sceneGroup and $sceneGroup.length > 0>>
<<for _pgid range $sceneGroup>>
<<set _pgc = State.variables[_pgid]>>
<<if _pgc and _pgc.met>>
<<capture _pgid>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getEventImagePath(_pgc.name)" style="width:100%; border-radius:8px; border:2px solid #9933cc; display:block;">
<div style="color:#cc88ff; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _pgc.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Corr: <<print _pgc.corr>>%</div>
</div>
<</capture>>
<</if>>
<</for>>
<</if>>
</div>
<<switch _id>>
<<case "Department Store">>
Chief Ember comes into the department store on official business and finds you with Quinn and Alina. Quinn is in an extremely tight, low-cut professional dress that barely contains her tits; Alina is in a sophisticated but obscenely short skirt and a sheer blouse.
<<speech "Ember">>"Miss Quinn. Miss Alina. I'm following up on some reports. Have either of you noticed any unusual activity or behaviour in town lately?"<</speech>>
<<speech "Quinn">>(smooth, professional, voice slightly husky) "Everything's been perfectly normal, Chief."<</speech>>
She keeps pressing her thighs together while she says it.
<<speech "Alina">>"I haven't observed anything out of the ordinary at the gym."<</speech>>
<<speech "Ember">>(a small pause) "…I hadn't got to the gym yet."<</speech>>
<<speech "Alina">>"Oh."<</speech>>
Her cheeks are flushed and her hands are trembling. She folds them to stop it.
<<speech "Ember">>"No matter."<</speech>>
She makes a note she plainly doesn't understand the meaning of.
<<speech "$name">>"What are you actually looking for, Chief?"<</speech>>
<<speech "Ember">>"Anything new. That's honestly the whole of it."<</speech>>
<<speech "Ember">>(bureaucratic, resigned) "Public order incidents are up ninefold and I've no cause for it. Not a drug, not a person, not a place. So I'm working through 'what's arrived in town lately' because it's the only list I've got left."<</speech>>
<<speech "Quinn">>"That sounds like a nightmare."<</speech>>
<<speech "Ember">>"It's a nightmare with paperwork."<</speech>>
She looks at the pair of them a moment longer — at the dress, at the blouse — and then away, and there's something almost like embarrassment in it.
<<speech "Ember">>"It's very warm in this shop."<</speech>>
<<speech "$name">>"Heating's been on all week."<</speech>>
<<speech "Ember">>"Mm. Anything comes to mind, the station'll take it."<</speech>>
She leaves seemingly satisfied and still watchful.
Quinn locks the changing room door the moment the shop doors close. Both women drop to their knees like depraved sluts — Quinn deepthroating you eagerly while Alina licks your balls, the two of them competing to be the nastiest cocksucker, moaning like whores with thick strings of saliva dripping down their chins until you finish across both their faces.
<<case "Electronics Store">>
Detective Angel comes into the electronics store looking like she's been on her feet since six. Kate is behind the counter in tiny shorts that ride up into her ass and a cropped tank showing underboob and hard nipples.
<<speech "Angel">>"Miss Kate. I need to know if anyone's bought any strange devices lately. Cameras, recording equipment, anything unusual."<</speech>>
<<speech "Kate">>(forcing the casual smile) "Nothing strange that I can remember. A few cameras for the school. Not much else."<</speech>>
Her face is flushed, her legs are unsteady, and there's a visible wet spot on the tiny shorts. She reaches for the terminal and her hand goes past it twice before it lands.
Angel watches the hand and doesn't say anything about it.
<<speech "$name">>"Are you expecting to find something?"<</speech>>
<<speech "Angel">>"Honestly? No. I'm eliminating."<</speech>>
<<speech "Angel">>(rubbing her eyes) "Twenty-two people in this town have started behaving unlike themselves, with no crime and no complaint attached. So either something's being done to them, or it's in the air, or I've lost my grip. And two of those three I can actually test."<</speech>>
<<speech "Kate">>"…Test how?"<</speech>>
<<speech "Angel">>"Can you order air quality monitors? Carbon monoxide, and whatever else there is to read. I don't know what I'm asking for, which is why I'm asking you."<</speech>>
<<speech "Kate">>"I can get two in."<</speech>>
<<speech "Angel">>"Do that."<</speech>>
She narrows her eyes at the counter, at the shop, at nothing in particular, and eventually leaves without a scrap of solid proof.
The second she's gone Kate pulls you into the storage room and drops to her knees, sucking your cock like a desperate whore.
<<speech "Kate">>(moaning between sloppy, gagging strokes) "I've been such a slut for you lately. I can't stop thinking about your cum."<</speech>>
She fingers herself furiously the whole time, gagging herself on you again and again until you paint her face, and she smears it into her skin with the flat of her hand.
<<case "Club">>
Officer Jane comes into the club during the early hours before opening and finds you with Lexi and Kali. Both girls are dressed like strippers — Lexi in a tiny skirt and cropped top, Kali in something even skimpier that barely covers anything at all.
Jane stops a good distance in. She forces the friendly smile, but there's clear unease in her eyes as she takes them in, and the heavy smell of sex in the room is doing something to her that she can't place.
<<speech "Jane">>"…Sorry. Miles away. Those outfits are really something. I'm just checking in — everything alright here?"<</speech>>
<<speech "Lexi">>(playing it cool, voice breathy, grinding subtly against you) "We're just having a normal night out, Officer. Nothing to worry about."<</speech>>
<<speech "Jane">>"It's five in the afternoon, love."<</speech>>
<<speech "Kali">>(laughing softly, cheeks burning) "Yeah, everything's chill here!"<</speech>>
She keeps giving you needy, submissive glances while she says it.
<<speech "Jane">>"Kali. Your mum does my hair. She said you'd stopped answering her — she wasn't cross about it, she was upset."<</speech>>
Kali's smile stays exactly where it is. Behind it, nothing turns over at all.
<<speech "$name">>"She's been busy."<</speech>>
<<speech "Jane">>"Aye."<</speech>>
<<speech "Jane">>(looking round at the empty room, the untouched bar, the bolted front doors) "I've been hearing worrying things lately and… I don't know. It feels off and I can't tell you why, and that's not like me. Nineteen of these conversations and everybody tells me they're fine, and they all mean it. Nobody's even lying to me. That's the part that's wrong."<</speech>>
She backs towards the door, tugging her collar loose, looking troubled and thoroughly conflicted about what she's just seen.
<<speech "Jane">>"Ring your mum, Kali."<</speech>>
The moment she's out, Lexi and Kali turn into filthy animals — Lexi sucking your cock like a desperate whore while Kali sits on your face, both of them moaning loudly into the empty club and calling you their owner as they cum hard.
Kali never does ring her mother.
<</switch>>
</div>
<<include "SuspicionScene-Footer">>
</div>/* ── SCENE GROUPS ── */
window.SCENE_GROUPS = {
"House": [
{ id: "House_Family", chars: ["elsa","jewelz","emily"], target: "LocationScene-Residential-Homes" },
{ id: "House_Godmother", chars: ["melissa","elsa","melody"], target: "LocationScene-Residential-Homes" }
],
"Neighbor's House": [{ id: "Neighbor_House_Twins", chars: ["demi","laila"], target: "LocationScene-Residential-Homes" }],
"Veruca's Class": [{ id: "Veruca_Class_Support", chars: ["riley","vina","kailey"], target: "LocationScene-Academic-Classes" }],
"Cousin's House": [{ id: "Cousin_Family", chars: ["lana","kylie","winter"], target: "LocationScene-Residential-Homes" }],
"Eva's House": [{ id: "Eva_House_Standard", chars: ["eva","alina","harmony"], target: "LocationScene-Residential-Homes" }],
"Mansion": [{ id: "Mansion_Standard", chars: ["haley","casey","luna"], target: "LocationScene-Residential-Homes" }],
"Aria's House": [{ id: "Aria_House_Standard", chars: ["aria","anya","ashly"], target: "LocationScene-Residential-Homes" }],
"Marie's Dorm": [{ id: "Marie_Dorm_Standard", chars: ["marie","blake","myra"], target: "LocationScene-Residential-Dorms" }],
"$name's Dorm": [
{ id: "Player_Dorm_Standard", chars: ["karlee","claire","scarlet"], target: "LocationScene-Residential-Dorms" },
{ id: "Player_Dorm_Tutoring", chars: ["avi","myra","karlee"], target: "LocationScene-Residential-Dorms" }
],
"Dormitory Hall": [{ id: "Dorm_Hall_Standard", chars: ["emily","kylie","laila"], target: "LocationScene-Residential-Dorms" }],
"Sorority House": [{ id: "Sorority_Standard", chars: ["nancy","yulia","avi"], target: "LocationScene-Residential-Dorms" }],
"Student Council": [{ id: "Student_Council_Standard", chars: ["adria","jade","gabbie"], target: "LocationScene-Academic-Classes" }],
"Detention Room": [{ id: "Detention_Standard", chars: ["ash","mia","rae"], target: "LocationScene-Academic-Classes" }],
"Chanel's Class": [{ id: "Chanel_Class_Standard", chars: ["chanel","violet","vanna"], target: "LocationScene-Academic-Classes" }],
"Library": [
{ id: "Library_Standard", chars: ["shazia","caprice","natalie"], target: "LocationScene-Academic-Common" },
{ id: "Library_Study", chars: ["kyler","adria","adriana"], target: "LocationScene-Academic-Common" }
],
"Cafeteria": [
{ id: "Cafeteria_Standard", chars: ["elsa","melody","christie"], target: "LocationScene-Academic-Common" },
{ id: "Cafeteria_Lunch", chars: ["scarlet","ashly","nancy"], target: "LocationScene-Academic-Common" }
],
"Mia's Class": [{ id: "Mia_Class_Before", chars: ["jade","rae","caprice"], target: "LocationScene-Academic-Classes" }],
"Cheerleader Track": [{ id: "Track_Standard", chars: ["isabella","lacy","athena"], target: "LocationScene-Academic-Common" }],
"School Pool": [{ id: "Pool_Standard", chars: ["aidra","ariana","harley"], target: "LocationScene-Academic-Common" }],
"Staff Room": [{ id: "Staff_Room_Standard", chars: ["chanel","veruca","adriana"], target: "LocationScene-Academic-Classes" }],
"School Hallway": [{ id: "Hallway_Gossip", chars: ["vanna","violet","maya"], target: "LocationScene-Academic-Common" }],
"School Rooftop": [{ id: "Rooftop_Standard", chars: ["kailey","scarlet","chloe"], target: "LocationScene-Academic-Common" }],
"Adriana's Class": [{ id: "Adriana_Class_Standard", chars: ["maya","yulia","adriana"], target: "LocationScene-Academic-Classes" }],
"Amber's Class": [{ id: "Amber_Class_Standard", chars: ["melody","chloe","amber"], target: "LocationScene-Academic-Classes" }],
"Office": [{ id: "Office_Standard", chars: ["megan","savannah","kyler"], target: "LocationScene-City-Civic" }],
"Gym": [
{ id: "Gym_Standard", chars: ["leah","alison","abella"], target: "LocationScene-City-Outdoor" },
{ id: "Gym_Session", chars: ["alina","ariana","anya"], target: "LocationScene-City-Outdoor" }
],
"Cinema": [
{ id: "Cinema_Standard", chars: ["lulu","molly","may"], target: "LocationScene-Mall-Leisure" },
{ id: "Cinema_Night", chars: ["kali","lana","jewelz"], target: "LocationScene-Mall-Leisure" }
],
"Town Hall": [{ id: "Town_Hall_Standard", chars: ["lily","nicole","carolina"], target: "LocationScene-City-Civic" }],
"Restaurant": [
{ id: "Restaurant_Workers", chars: ["kendra","jasmine","katie"], target: "LocationScene-City-Nightlife" },
{ id: "Restaurant_Date", chars: ["blake","marie","aria"], target: "LocationScene-City-Nightlife" }
],
"Hotel": [{ id: "Hotel_Standard", chars: ["momo","caitlyn","stella"], target: "LocationScene-City-Nightlife" }],
"Spa": [
{ id: "Spa_Standard", chars: ["nikki","autumn","keisha"], target: "LocationScene-Mall-Leisure" },
{ id: "Spa_Afternoon", chars: ["alex","emily","isabella"], target: "LocationScene-Mall-Leisure" }
],
"Club": [
{ id: "Club_Standard", chars: ["lexi","leda","avery"], target: "LocationScene-City-Nightlife" },
{ id: "Club_Night", chars: ["claire","maya","caitlyn"], target: "LocationScene-City-Nightlife" }
],
"Real Estate": [{ id: "Real_Estate_Standard", chars: ["quinn","kenna"], target: "LocationScene-Mall-Leisure" }],
"Police Station": [{ id: "Police_Standard", chars: ["angel","ember","jane"], target: "LocationScene-City-Civic" }],
"Courthouse": [{ id: "Courthouse_Standard", chars: ["jessa","winter"], target: "LocationScene-City-Civic" }],
"Beach": [{ id: "Beach_Standard", chars: ["alex","gina","marie"], target: "LocationScene-City-Outdoor" }],
"Park": [
{ id: "Park_EvaRiley", chars: ["eva","riley"], target: "LocationScene-City-Outdoor" },
{ id: "Park_Triad", chars: ["aria","isabella","eva"], target: "LocationScene-City-Outdoor" }
],
"Town Square": [{ id: "Town_Square_Standard", chars: ["uma","lana","casey"], target: "LocationScene-City-Outdoor" }],
"Clothing Store": [{ id: "Clothing_Store_Standard", chars: ["skylar","melissa","vina"], target: "LocationScene-Mall-Retail" }],
"Electronics Store": [{ id: "Electronics_Standard", chars: ["kate","demi"], target: "LocationScene-Mall-Retail" }],
"Department Store": [{ id: "Dept_Store_Standard", chars: ["kali","jewelz"], target: "LocationScene-Mall-Retail" }],
"Arcade": [
{ id: "Arcade_Standard", chars: ["natalia","kenzie","madi"], target: "LocationScene-Mall-Leisure" },
{ id: "Arcade_Afternoon", chars: ["gina","harmony","kylie"], target: "LocationScene-Mall-Leisure" }
]
};
/* ── SUSPICION SCENE DATA ── */
window.SUS_DATA = {
"House": { agent: "jane", res: ["jewelz"], req: 75, target: "SuspicionScene-Residential" },
"Cousin's House": { agent: "jane", res: ["winter"], req: 75, target: "SuspicionScene-Residential" },
"Eva's House": { agent: "angel", res: ["eva"], req: 75, target: "SuspicionScene-Residential" },
"Mansion": { agent: "ember", res: ["luna"], req: 50, target: "SuspicionScene-Residential" },
"Sorority House": { agent: "angel", res: ["nancy"], req: 75, target: "SuspicionScene-Residential" },
"Dormitory Hall": { agent: "angel", res: ["myra","melody"], req: 50, target: "SuspicionScene-Residential" },
"School Hallway": { agent: "angel", res: ["violet"], req: 50, target: "SuspicionScene-Academic" },
"School Rooftop": { agent: "angel", res: ["abella","caprice"], req: 75, target: "SuspicionScene-Academic" },
"Staff Room": { agent: "jane", res: ["veruca","anya"], req: 75, target: "SuspicionScene-Academic" },
"Student Council": { agent: "ember", res: ["carolina","adria"], req: 75, target: "SuspicionScene-Academic" },
"Cafeteria": { agent: "angel", res: ["natalie","karlee"], req: 50, target: "SuspicionScene-Academic" },
"Cheerleader Track": { agent: "jane", res: ["lacy","blake"], req: 75, target: "SuspicionScene-Academic" },
"School Pool": { agent: "angel", res: ["ariana","harley"], req: 75, target: "SuspicionScene-Academic" },
"Town Square": { agent: "jane", res: ["kailey","vina"], req: 50, target: "SuspicionScene-Town" },
"Hotel": { agent: "angel", res: ["caitlyn"], req: 75, target: "SuspicionScene-Town" },
"Park": { agent: "jane", res: ["maya","casey"], req: 50, target: "SuspicionScene-Town" },
"Beach": { agent: "jane", res: ["uma","rae"], req: 75, target: "SuspicionScene-Town" },
"Town Hall": { agent: "ember", res: ["lily"], req: 75, target: "SuspicionScene-Town" },
"Department Store": { agent: "ember", res: ["quinn","alina"], req: 50, target: "SuspicionScene-Entertainment" },
"Electronics Store": { agent: "angel", res: ["kate"], req: 50, target: "SuspicionScene-Entertainment" },
"Club": { agent: "jane", res: ["lexi","kali"], req: 50, target: "SuspicionScene-Entertainment" }
};
/* ── GET SCENE TIER ── */
window.getSceneTier = function(chars) {
var sv = State.variables;
var min = 100;
for (var i = 0; i < chars.length; i++) {
var c = sv[chars[i]];
var corr = c ? (c.corr || 0) : 0;
if (corr < min) min = corr;
}
if (min < 25) return 1; /* 0–24 including 0 = early game */
if (min < 50) return 2;
if (min < 75) return 3;
return 4;
};
/* ── ROLL DAILY SCENES ───────────────────────────────────────────────────
Called from DayStart after assignDailyLocations.
Picks one location scene and one suspicion scene (if eligible) for
today and stores them in $availableScenes.
Like activities, scenes only appear on the day they are rolled.
────────────────────────────────────────────────────────────────────── */
window.rollDailyScenes = function() {
var sv = State.variables;
if (!sv.seenScenes) sv.seenScenes = {};
sv.availableScenes = {};
/* Roll location scenes: 40% chance per eligible location */
Object.keys(window.SCENE_GROUPS).forEach(function(loc) {
if (Math.random() > 0.40) return;
var result = window.findValidLocationScene(loc);
if (result) sv.availableScenes[loc] = { type: "location", sceneId: result.id, chars: result.chars, tier: result._tier, key: result._key, target: result.target };
});
/* Roll suspicion scenes: only if suspicion > 50, 60% chance per eligible location */
if ((sv.suspicion || 0) > 50) {
Object.keys(window.SUS_DATA).forEach(function(loc) {
if (Math.random() > 0.60) return;
var result = window.findValidSuspicionScene(loc);
if (result) sv.availableScenes[loc] = { type: "suspicion", chars: result.res, agent: result.agent, target: result.target };
});
}
};
/* ── FIND VALID LOCATION SCENE ── */
/* Returns scene data object or null. Does NOT mutate the scene object. */
window.findValidLocationScene = function(loc) {
var sv = State.variables;
var pool = window.SCENE_GROUPS[loc];
if (!pool) return null;
if (!sv.seenScenes) sv.seenScenes = {};
var found = null;
for (var i = 0; i < pool.length; i++) {
var s = pool[i];
var allMet = true;
for (var j = 0; j < s.chars.length; j++) {
var c = sv[s.chars[j]];
if (!c || !c.met) { allMet = false; break; }
}
if (!allMet) continue;
var tier = window.getSceneTier(s.chars);
var key = s.id + "-T" + tier;
if (sv.seenScenes[key]) continue;
/* Return a fresh object — never mutate the definition */
found = { id: s.id, chars: s.chars, target: s.target, _tier: tier, _key: key };
break;
}
return found;
};
/* ── FIND VALID SUSPICION SCENE ── */
window.findValidSuspicionScene = function(loc) {
var sv = State.variables;
if (!sv.seenScenes) sv.seenScenes = {};
var s = window.SUS_DATA[loc];
if (!s) return null;
if ((sv.suspicion || 0) <= 50) return null;
/* SuspicionScene-Router writes sv.seenScenes["SUS-" + loc] after playing
one, but nothing ever READ it — so the same scene re-rolled every night
for as long as suspicion stayed above 50. There is exactly one suspicion
scene per location, so once it is seen the location is spent. */
if (sv.seenScenes["SUS-" + loc]) return null;
var agent = sv[s.agent];
if (!agent || agent.infected) return null;
for (var i = 0; i < s.res.length; i++) {
var r = sv[s.res[i]];
if (!r || !r.met || r.corr < s.req) return null;
}
return s;
};[[Go Back|TownHub]]
<<nobr>>
<h1 style="color:#bd59ff; text-align:center; margin-bottom:20px;">⚙ Settings</h1>
<div style="display:flex; flex-direction:column; gap:12px; max-width:500px; margin:0 auto;">
/* ── FACTION SIZE ── */
<div style="background:#0d0d1a; border:1px solid #2a0050; border-radius:8px; padding:12px 16px;">
<div style="font-size:0.82em; font-weight:bold; color:#bd59ff; margin-bottom:6px;">Max Faction Size</div>
<div style="color:#666; font-size:0.75em; margin-bottom:10px;">How many members a faction can recruit before it stops growing.</div>
<div style="color:#7a6a4a; font-size:0.72em; margin-bottom:10px; line-height:1.5;">Lowering this does not break up factions that already exist. A faction over the new limit simply stops recruiting until attrition brings it back under.</div>
<div style="display:flex; align-items:center; gap:12px;">
<<button "−">>
<<if $settings.factionMaxSize > 4>>
<<set $settings.factionMaxSize -= 1>>
<</if>>
<<goto "Settings">>
<</button>>
<span style="color:#fff; font-size:1.2em; font-weight:bold; min-width:30px; text-align:center;"><<print $settings.factionMaxSize>></span>
<<button "+">>
<<if $settings.factionMaxSize < 10>>
<<set $settings.factionMaxSize += 1>>
<</if>>
<<goto "Settings">>
<</button>>
<span style="color:#555; font-size:0.78em; margin-left:4px;">(4 – 10)</span>
</div>
</div>
/* ── VIDEO MODE ── */
<div style="background:#0d0d1a; border:1px solid #2a0050; border-radius:8px; padding:12px 16px;">
<<set _vmLabels = {
"randomized": "Randomized — one random clip per tier unlocked",
"primary": "Primary only — Mast, BJ and Sex, one per tier",
"all": "All — every tier shown",
"last2": "Last 2 levels — highest two tiers only",
"last1": "Last level — highest tier only"
}>>
<<set _vmShort = {
"randomized": "Randomized",
"primary": "Primary only",
"all": "All tiers",
"last2": "Last 2 levels",
"last1": "Last level"
}>>
<<set _vmCur = ($settings && $settings.videoMode) ? $settings.videoMode : "randomized">>
<div style="display:flex; justify-content:space-between; align-items:baseline; margin-bottom:6px;">
<span style="font-size:0.82em; font-weight:bold; color:#bd59ff;">Video Display Mode</span>
<span style="font-size:0.78em; color:#44ff88; background:#001a0d; border:1px solid #1e5a3a; border-radius:12px; padding:2px 10px;">
Active: <b><<print _vmShort[_vmCur]>></b>
</span>
</div>
<div style="color:#666; font-size:0.75em; margin-bottom:10px;">Which corruption tiers are shown in group and character video scenes.</div>
<div style="display:flex; flex-direction:column; gap:6px;">
<<for _vm range ["randomized", "primary", "all", "last2", "last1"]>>
<<capture _vm>>
<<set _active = $settings.videoMode is _vm>>
<div style="display:flex; align-items:center; gap:10px; padding:6px 8px; border-radius:5px;
background:<<if _active>>#1a0030<<else>>#0a0a0a<</if>>;
border:1px solid <<if _active>>#9c27b0<<else>>#111<</if>>;">
<div style="width:12px; height:12px; border-radius:50%; flex-shrink:0;
border:2px solid <<if _active>>#bd59ff<<else>>#333<</if>>;
background:<<if _active>>#bd59ff<<else>>#000<</if>>;"></div>
<<if _active>>
<span style="color:#bd59ff; font-weight:bold; font-size:0.88em;">✓ <<print _vmLabels[_vm]>></span>
<span style="color:#44ff88; font-size:0.72em; margin-left:auto; white-space:nowrap;">ACTIVE</span>
<<else>>
<<button _vmLabels[_vm]>>
<<set $settings.videoMode = _vm>>
<<goto "Settings">>
<</button>>
<</if>>
</div>
<</capture>>
<</for>>
</div>
</div>
/* ── AUTOMATIC INFECTION ── */
<div style="background:#0d0d1a; border:1px solid #2a0050; border-radius:8px; padding:12px 16px;">
<<set _aiOn = !$settings or $settings.autoInfect isnot false>>
<div style="display:flex; justify-content:space-between; align-items:baseline; margin-bottom:6px;">
<span style="font-size:0.82em; font-weight:bold; color:#bd59ff;">Automatic Infection</span>
<span style="font-size:0.78em; border-radius:12px; padding:2px 10px;
color:<<if _aiOn>>#44ff88<<else>>#ff9944<</if>>;
background:<<if _aiOn>>#001a0d<<else>>#1a0f00<</if>>;
border:1px solid <<if _aiOn>>#1e5a3a<<else>>#5a3a1a<</if>>;">
<<if _aiOn>>On<<else>>Off<</if>>
</span>
</div>
<div style="color:#666; font-size:0.75em; margin-bottom:10px;">Whether the parasite takes girls on its own overnight — vectors seeding someone new, nests catching a passer-by, and the two Location Control upgrades.</div>
<div style="color:#7a6a4a; font-size:0.72em; margin-bottom:10px; line-height:1.5;">Turning this off never blocks anything you asked for: the Infect button, taking a captive, and parties or activities you attend all still work. Nests you have already planted keep spreading — only a bred girl spawning a <b>new</b> nest is stopped. Girls who are already infected still deepen normally.</div>
<<if _aiOn>>
<<button "Turn off">>
<<set $settings.autoInfect = false>>
<<goto "Settings">>
<</button>>
<<else>>
<<button "Turn on">>
<<set $settings.autoInfect = true>>
<<goto "Settings">>
<</button>>
<</if>>
</div>
/* ── GIRLS PER SCENE ── */
<div style="background:#0d0d1a; border:1px solid #2a0050; border-radius:8px; padding:12px 16px;">
<div style="font-size:0.82em; font-weight:bold; color:#bd59ff; margin-bottom:6px;">Girls Per Scene</div>
<div style="color:#666; font-size:0.75em; margin-bottom:10px;">Max number of girls shown in Group Interact and Activity scenes.</div>
<div style="display:flex; align-items:center; gap:12px;">
<<button "−">>
<<if $settings.girlsPerScene > 1>>
<<set $settings.girlsPerScene -= 1>>
<</if>>
<<goto "Settings">>
<</button>>
<span style="color:#fff; font-size:1.2em; font-weight:bold; min-width:30px; text-align:center;"><<print $settings.girlsPerScene>></span>
<<button "+">>
<<if $settings.girlsPerScene < 7>>
<<set $settings.girlsPerScene += 1>>
<</if>>
<<goto "Settings">>
<</button>>
<span style="color:#555; font-size:0.78em; margin-left:4px;">(1 – 7)</span>
</div>
</div>
</div>
<div style="text-align:center; margin-top:20px;">
<<button "← Back">><<goto "TownHub">><</button>>
</div>
<</nobr>><<nobr>>
<<set _newLvl = $pendingLevelUpScene || $parasiteLevel>>
<<set _lvlNames = [null, "Hatchling", "Juvenile", "Mature", "Apex"]>>
<<set _lvlColors = [null, "#88aaff", "#44cc88", "#ffaa44", "#ff5555"]>>
<<set _color = _lvlColors[_newLvl] || "#bd59ff">>
<<set _name = _lvlNames[_newLvl] || "Unknown">>
<<set _lvlData = {
2: {
scene: "You wake before the alarm with the taste of copper at the back of your throat and the distinct sense that something in you has finished settling.<br><br>" +
"It has stopped feeling like a passenger. Yesterday you could point to where it ended and where you began — a pressure behind the eyes, a second opinion arriving in your own voice. This morning you look for that seam and cannot find it. The thought <em>she would be easier to reach on a Thursday</em> arrives, and you have no idea which of you produced it.<br><br>" +
"It hasn't taken anything by force. It has simply moved in and started rearranging, and you have been helping.",
urge: "The hunger is still recognisable as hunger. You look at a woman and want her, and it feels like wanting, and you can still tell yourself that is all it is. It only lasts a moment. It has always lasted a moment. It is just that it now happens to everyone.",
summary: "The parasite has found its footing. The network is real now — you can feel each thread of it. It is no longer just a tool. It is becoming something that thinks.",
bonus: "Hivemind capacity expanded. Nest ceiling raised. Infection power increased."
},
3: {
scene: "It doesn't whisper any more. That was the part you had learned to argue with.<br><br>" +
"Now you simply know things. Where each of them is. Which of them slept badly. Which one is at this moment thinking about you and constructing a reason to walk past. The knowledge arrives without language, the way you know your own hand is behind your back, and you have stopped being startled by it.<br><br>" +
"You find yourself counting them in the night — not names, just the shape of how many, the weight of the thing you are carrying. Somewhere in the last few weeks you stopped saying <em>it</em> and started saying <em>we</em>, and nobody corrected you, because there is nobody left in your head to do it.",
urge: "It is not about wanting them any more. Wanting was a thing with an ending. This is arithmetic — how many, how deep, how soon, and the flat certainty that every one of them should be <em>filled</em>. You catch yourself calculating a girl's cycle before you have registered her face. The word <em>breed</em> surfaces in your own thinking, unremarkable, already familiar, and you do not flinch at it.",
summary: "A threshold has been crossed that cannot be uncrossed. The hivemind breathes on its own now. You are no longer spreading an infection — you are growing a mind.",
bonus: "The network deepens. More can be held. More can be corrupted."
},
4: {
scene: "There was no final moment. You keep looking for one and it isn't there.<br><br>" +
"Nothing is left of the arrangement — no host, no passenger, no negotiation between them. What sits in your chest is single and enormous and entirely calm, and it has your memories, your voice, their $familymale's face, and it wants what it has always wanted with a patience that no longer needs hurrying.<br><br>" +
"You can feel the whole shape of it now. Every one of them, out there in the dark, going about a day that is already yours. None of them know. It doesn't matter that they don't know. The city has been rewritten around a single purpose and it is still setting the tables and opening the shops.",
urge: "There is no urge. An urge is something a body has and can decline. This is simply what you are for.<br><br>" +
"Every woman in this town is a place the future could be put, and you have all the time there is. You will fill them. Not tonight, not in a rush — thoroughly, one after another, until there is nothing here that isn't yours and isn't carrying.",
summary: "Apex. The word settles like a fact. The city doesn't know it yet, but it already belongs to the parasite. Every infected girl is a node. Every node feeds the whole.",
bonus: "Ceilings raised to their limit — 70 held at once, 14 nests, infection power 20."
}
}[_newLvl] || {
scene: "",
urge: "",
summary: "The parasite evolves.",
bonus: ""
}>>
<</nobr>>
<div style="text-align:center; padding:0 20px 40px;">
<div style="border-bottom:2px solid <<print _color>>; padding-bottom:16px; margin-bottom:28px;">
<div style="font-size:0.8em; text-transform:uppercase; letter-spacing:0.16em; color:#555; margin-bottom:8px;">Evolution Complete</div>
<h1 style="margin:0; color:<<print _color>>; font-size:2.4em; font-weight:bold;"><<print _name>></h1>
<div style="color:#666; font-size:1em; margin-top:6px;">Parasite Level <<print _newLvl>> reached</div>
</div>
/* ── LEVEL TRACK ── */
<div style="display:flex; align-items:center; max-width:360px; margin:0 auto 32px;">
<<for _li to 1; _li lte 4; _li++>>
<div style="flex:1; text-align:center;">
<div style="width:32px; height:32px; border-radius:50%; margin:0 auto;
display:flex; align-items:center; justify-content:center;
font-weight:bold; font-size:0.9em;
background:<<if _li lte _newLvl>><<print _lvlColors[_li]>><<else>>#111<</if>>;
border:2px solid <<if _li lte _newLvl>><<print _lvlColors[_li]>><<else>>#333<</if>>;
color:<<if _li lte _newLvl>>#000<<else>>#444<</if>>;">
<<if _li lt _newLvl>>✓<<else>><<print _li>><</if>>
</div>
<div style="font-size:0.65em; margin-top:4px; color:<<if _li lte _newLvl>><<print _lvlColors[_li]>><<else>>#444<</if>>;">
<<print [null,"Hatchling","Juvenile","Mature","Apex"][_li]>>
</div>
</div>
<<if _li lt 4>>
<div style="height:2px; flex:1; background:<<if _li lt _newLvl>><<print _lvlColors[_li]>><<else>>#222<</if>>; margin-bottom:20px;"></div>
<</if>>
<</for>>
</div>
/* ── THE FUSION ── */
<<if _lvlData.scene>>
<div style="background:#0a000f; border:1px solid <<print _color>>44; border-radius:8px; padding:20px 24px; max-width:560px; margin:0 auto 20px; color:#ddd; line-height:1.85; font-size:0.97em; text-align:left;">
<<print _lvlData.scene>>
</div>
<</if>>
/* ── THE HUNGER ── */
<<if _lvlData.urge>>
<div style="background:#12000a; border-left:4px solid #ff4477; border-radius:0 8px 8px 0; padding:18px 22px; max-width:560px; margin:0 auto 24px; color:#e8b8c8; line-height:1.85; font-size:0.97em; text-align:left;">
<div style="font-size:0.72em; text-transform:uppercase; letter-spacing:0.14em; color:#ff4477; margin-bottom:10px; font-weight:bold;">The Hunger</div>
<<print _lvlData.urge>>
</div>
<</if>>
/* ── SUMMARY ── */
<div style="background:#111; border-left:4px solid <<print _color>>; border-radius:0 8px 8px 0; padding:18px 22px; max-width:520px; margin:0 auto 24px; font-style:italic; color:#ccc; line-height:1.8; font-size:1em; text-align:left;">
<<print _lvlData.summary>>
</div>
/* ── BONUSES ── */
<div style="background:#0d0018; border:1px solid <<print _color>>33; border-radius:8px; padding:14px 18px; max-width:520px; margin:0 auto 32px; text-align:left;">
<div style="font-size:0.8em; text-transform:uppercase; letter-spacing:0.1em; color:<<print _color>>; margin-bottom:8px; font-weight:bold;">Bonuses Applied</div>
<div style="color:#aaa; font-size:0.92em; line-height:1.7;">
<div>🪹 Nest cap ceiling +2</div>
<div>🧠 Hivemind cap ceiling +10</div>
<div>☣ Infection power ceiling +1</div>
<<if _lvlData.bonus>><div style="color:<<print _color>>; margin-top:6px;"><<print _lvlData.bonus>></div><</if>>
</div>
</div>
<div style="text-align:center;">
<<button "Continue">>
<<set $pendingLevelUpScene = null>>
<<goto "Upgrades">>
<</button>>
</div>
</div><<nobr>>
<<if !$capBreakTarget>><<goto "TownHub">><</if>>
<<set _c = State.variables[$capBreakTarget]>>
<<if !_c>><<goto "TownHub">><</if>>
<<set _img = window.getEventImagePath(_c.name)>>
<<set _newCap = window.getCorrCap ? window.getCorrCap($capBreakTarget) : 25>>
<<set _oldCap = Math.max(0, _newCap - 25)>>
<<set _capColors = { 25: "#88aaff", 50: "#bd59ff", 75: "#ff88cc", 100: "#ff4444" }>>
<<set _color = _capColors[_newCap] || "#bd59ff">>
<<set _ret = $capBreakReturn || "TownHub">>
<</nobr>>
<div style="text-align:center; padding:0 20px 32px;">
<div style="border-bottom:2px solid <<print _color>>; padding-bottom:14px; margin-bottom:24px;">
<div style="font-size:0.75em; color:#555; text-transform:uppercase; letter-spacing:0.12em; margin-bottom:6px;">Cap Broken</div>
<h1 style="margin:0; color:<<print _color>>; font-size:2em;">⬆ Threshold Crossed</h1>
<div style="color:#666; font-size:0.9em; margin-top:6px;"><<print _c.name>></div>
</div>
<div style="margin-bottom:24px;">
<img @src="_img" style="max-width:320px; width:80%; border-radius:10px; border:3px solid <<print _color>>; display:block; margin:0 auto;">
</div>
/* ── CAP PROGRESS ── */
<div style="max-width:400px; margin:0 auto 20px;">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
<div style="text-align:center; flex:1;">
<div style="font-size:0.75em; color:#555; margin-bottom:3px;">Previous Cap</div>
<div style="font-size:1.3em; font-weight:bold; color:#555; text-decoration:line-through;"><<print _oldCap>></div>
</div>
<div style="color:<<print _color>>; font-size:1.8em; flex-shrink:0; padding:0 12px;">→</div>
<div style="text-align:center; flex:1;">
<div style="font-size:0.75em; color:#aaa; margin-bottom:3px;">New Cap</div>
<div style="font-size:1.3em; font-weight:bold;" @style="'color:' + _color + ';'"><<print _newCap>></div>
</div>
</div>
<div style="background:#111; height:6px; border-radius:3px; overflow:hidden;">
<div @style="'width:' + _c.corr + '%; height:100%; background:' + _color + '; transition:width 0.5s;'"></div>
</div>
<div style="display:flex; justify-content:space-between; font-size:0.65em; color:#333; margin-top:3px;">
<span>0</span><span>25</span><span>50</span><span>75</span><span>100</span>
</div>
<div style="text-align:right; font-size:0.75em; color:#555; margin-top:4px;">Corruption: <<print _c.corr>>%</div>
</div>
/* ── NARRATIVE ── */
<div style="background:#0d0d1a; border-left:3px solid <<print _color>>; border-radius:0 6px 6px 0; padding:14px 18px; margin:0 auto 24px; max-width:480px; font-style:italic; color:#ccc; line-height:1.7; font-size:0.92em; text-align:left;">
<<if _newCap is 50>>
Something gives way inside her. The resistance she didn't know she was holding — gone. She can go further now, and some part of her already knows it.
<<elseif _newCap is 75>>
The last rational wall has cracked. What remains is instinct, warmth, and the quiet certainty that she belongs to this. To you.
<<elseif _newCap is 100>>
There is nothing left to break. She is fully open to the parasite now — a willing vessel, a node in the network. Complete.
<<else>>
The threshold shifts. She can go further now.
<</if>>
</div>
<div style="text-align:center;">
<<button "Continue">>
<<set $capBreakTarget = null>>
<<set $capBreakReturn = null>>
<<goto _ret>>
<</button>>
</div>
</div><<set _threshold = $activeSuspicionThreshold || 50>>
<div style="background:#1a0000; border:1px solid #ff4444; border-radius:6px; padding:10px 14px; margin:16px 0; text-align:center;">
<span style="color:#ff6666; font-size:0.85em;">
Authority is investigating a host exceeding the <<print _threshold>>% threshold.
</span>
</div>
<div style="text-align:center;">
<<button "Withdraw Quietly">>
<<set $activeSuspicionAgent = null>>
<<set $activeSuspicionResidents = null>>
<<set $activeSuspicionThreshold = null>>
<<set $sceneLocation = null>>
<<set $sceneGroup = []>>
<<set $activeSceneID = "">>
<<goto "TownHub">>
<</button>>
</div>
<<set $sceneColor = "#ffcc44">>
<<set $sceneLabel = "Academic · Classes">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "Adriana_Class_Standard">>
<<if _tier is 0 or _tier is 1>>
The classroom hums with the quiet energy of focused study. The late afternoon sun slants through the windows, casting long shadows over the desks. Professor Adriana stands at the front, her blouse buttoned primly, her skirt falling just above her knees. She gestures animatedly as she explains a point, her voice warm and engaging. Yulia sits near the front, her notebook open, her pen moving methodically as she takes notes. Maya lounges in the back, her legs crossed, a smile playing on her lips as she listens. $name slips into the room, his eyes scanning for Emily—not here yet.
Adriana spots him and smiles. <<speech "Adriana">>"$name! Come in. We’re just discussing cultural assimilation—something you’ve got firsthand experience with, given your work with exchange students."<</speech>> She adjusts her glasses, her gaze lingering on him a second too long—just friendly concern.
Yulia glances up, her cheeks pinkening slightly. <<speech "Yulia">>"Ah, $name. You are looking for Emily, yes?"<</speech>> Her accent is soft, her voice barely above a whisper.
Maya grins, spinning her pen between her fingers. <<speech "Maya">>"She’s probably in the library again. You know how she gets when she’s researching."<</speech>> She tilts her head, her ponytail swinging. <<speech "Maya">>"You could’ve just texted her, you know."<</speech>>
$name rubs the back of his neck. <<speech "$name">>"She’s not answering. I just wanted to make sure she’s okay."<</speech>> His voice is rough with worry—she’s been jumpy lately.
Adriana’s expression softens. <<speech "Adriana">>"She’s a strong girl, $name. But if you’re worried, you can check the student lounge. She mentioned something about a group project."<</speech>> She steps closer, her hand brushing his arm—comforting, maternal. <<speech "Adriana">>"You take such good care of her. It’s admirable."<</speech>>
Yulia ducks her head, her fingers twisting together. <<speech "Yulia">>"If she is not there, perhaps she went to the dorm early? She was… tired this morning."<</speech>> Her voice is hesitant, her dark eyes flicking to $name before darting away.
Maya smirks. <<speech "Maya">>"Or maybe she’s avoiding you because you’re being overprotective again."<</speech>> She winks, nudging his shoe with her foot. <<speech "Maya">>"You know she hates that."<</speech>>
$name exhales, running a hand through his hair. <<speech "$name">>"Yeah, yeah. I’ll check the lounge."<</speech>> He turns to leave, but Adriana’s hand on his shoulder stops him.
<<speech "Adriana">>"$name."<</speech>> Her voice is gentle, her thumb tracing a small circle on his shirt. <<speech "Adriana">>"If she needs anything—anything—you tell her to come to me, alright? My door is always open. The same goes for you."<</speech>>
He nods, but his skin burns where she touches him.
<<elseif _tier is 2>>
The parasite thrums in $name’s chest, its tendrils coiling around his nerves, heightening every sensation. The classroom feels warmer, the air thick with the scent of perfume and something sweeter—arousal. Adriana’s blouse is unbuttoned just enough to tease the lace edge of her bra, her skirt riding up when she moves. Yulia’s sweater clings to her curves, her fingers twitching at her collar like she’s too hot. Maya’s tank top is stretched tight over her chest, her nipples hard beneath the fabric, her legs crossed and squeezed tight.
Adriana looks up as $name enters, her lips parting, her tongue darting out to wet them. <<speech "Adriana">>"$name…"<</speech>> Her voice is softer, breathier. <<speech "Adriana">>"You’re looking for Emily?"<</speech>> She steps closer, her hips swaying just a little more than usual. Her hand lifts, her fingers brushing his chest—accidentally, of course.
Yulia’s pen snaps in her grip. She gasps, her cheeks flaming as she stares at the ink bleeding onto her notebook. <<speech "Yulia">>"Ah—! N-$name…"<</speech>> Her voice is a whisper, her thighs pressing together under her desk.
Maya licks her lips, her eyes dark as she watches Adriana’s fingers trail down $name’s arm. <<speech "Maya">>"She’s not here. But you can… stay awhile."<</speech>> Her voice is a purr, her foot sliding up his calf under the desk.
$name’s breath hitches. The parasite whispers: They want you. Take them.
<<speech "$name">>"H-Have you seen her?"<</speech>> His voice is rougher, deeper. His hand twitches, his fingers curling into a fist to keep from reaching out.
Adriana’s lips curl. <<speech "Adriana">>"Not since this morning. But you’re welcome to wait."<</speech>> Her hand slides to his waist, her thumb hooking into his belt loop. <<speech "Adriana">>"We were just discussing… intimacy in different cultures."<</speech>> Her gaze drops to his lips.
Yulia lets out a whimper, her fingers digging into her thighs. <<speech "Yulia">>"I-I saw her in the library… earlier…"<</speech>> Her voice is strained, her breath coming faster.
Maya leans forward, her elbows on her desk, giving $name a perfect view down her top. <<speech "Maya">>"Or you could help us with the discussion. Firsthand experience and all."<</speech>> She grins, her teeth sinking into her lower lip.
$name’s control snaps.
His hand grips Adriana’s hip, pulling her against him. She gasps, her body melting into his, her fingers clutching at his shirt. <<speech "$name">>"Professor…"<</speech>> His voice is a growl. <<speech "$name">>"You shouldn’t tease."<</speech>>
Yulia moans, her hand slipping between her thighs, her skirt riding up as she grinds into her own fingers. Maya stands, her chair scraping back as she presses against $name’s other side, her mouth finding his neck.
<<speech "Maya">>"Fuck Emily,"<</speech>> Maya whispers, her tongue dragging up his throat. <<speech "Maya">>"Stay with us."<</speech>>
The parasite laughs.
<<elseif _tier is 3>>
The classroom is empty—or it should be.The blinds are drawn, the only light coming from the projector, casting long shadows that make the desks look like altars.
Adriana is on her knees before $name even fully enters the room, her blouse torn open, her bra pushed up to frame her heavy breasts. Yulia sits on the edge of a desk, her skirt hitched up, her panties gone, her fingers buried inside herself as she whimpers. Maya lounges on Adriana’s desk, her legs spread, her tank top ripped to expose her nipples, her hand working between her thighs.
<<speech "Adriana">>"$name…"<</speech>> Adriana breathes, her voice a moan. Her hands are already at his belt, her fingers fumbling in her haste. <<speech "Adriana">>"We were talking about you…"<</speech>> Her tongue darts out, swirling over the head of his cock as she frees it. <<speech "Adriana">>"About how good you’d feel…"<</speech>>
Yulia whines, her fingers squishing as she fucks herself. <<speech "Yulia">>"P-Please… I n-need to taste you too…"<</speech>> Her voice is broken, her accent thicker with desire.
Maya grins, her fingers glistening as she pulls them from her pussy and sucks them clean. <<speech "Maya">>"C’mon, Yulia. Share."<</speech>> She slides off the desk, crawling to $name’s other side, her mouth joining Adriana’s as they worship his cock together.
$name groans, his hands tangling in their hair. <<speech "$name">>"Fuck—"*<</speech>> His hips jerk forward, his cock hitting the back of Adriana’s throat. She gags, but her hands only tighten on his ass, pulling him deeper.
Yulia crawls forward, her mouth replacing Maya’s as they take turns, their tongues swirling over his shaft, their lips smacking wetly. <<speech "Yulia">>"Y-You taste so good…"<</speech>> Her voice is a sob, her free hand groping at her own breast.
Maya moans, her mouth stretching around him as she takes him to the root. <<speech "Maya">>"Mmm—fuck, you’re huge…"<</speech>> She pulls back, her lips popping off the head. <<speech "Maya">>"I bet Emily never sucked you like this."<</speech>> She winks, before diving back in, her throat fluttering around him.
Adriana’s hands roam, one slipping into her own panties, her fingers circling her clit as she chokes on his cock. <<speech "Adriana">>"G-Good boy…"<</speech>> she gasps. <<speech "Adriana">>"Let us worship you…"<</speech>>
The parasite purrs: Make them drown in you.
<<else>>
The classroom isn’t a classroom anymore. It’s a breeding chamber, the walls slick with condensation, the air thick with the scent of sex and submission. The parasite has rewritten them—mind, body, soul.
Adriana is naked, her body marked with the parasite’s creeping veins, her tits heavy and swollen, her cunt dripping onto the floor. Yulia is bent over a desk, her ass in the air, her pussy clenching around nothing, her moans slurred and desperate. Maya is spread on the professor’s chair, her legs hooked over the arms, her fingers stretching her cunt open in offering.
<<speech "Adriana">>"N-$name…"<</speech>> Adriana whines, crawling toward him, her nails scoring the floor. <<speech "Adriana">>"We were supposed to be discussing culture…"<</speech>> She giggles, the sound broken. <<speech "Adriana">>"But maybe... your cock is more interesting…"<</speech>> Her hands grope at him, her mouth drooling in anticipation.
Yulia sobs, her hips rocking back, her ass jiggling. <<speech "Yulia">>"P-Please… I c-can’t think anymore…"<</speech>> Her voice is guttural, her accent thick with need. <<speech "Yulia">>"Just fuck me… Breed me…"<</speech>>
Maya spreads herself wider, her fingers plunging into her pussy. <<speech "Maya">>"I-I love you…"<</speech>> Her words are slurred, her eyes empty of everything but devotion. <<speech "Maya">>"F-Fill me up…"<</speech>>
$name grins—or rather, the parasite grins through him.
He slams into Yulia first, her tight cunt swallowing him whole as she screams, her nails scoring the desk. Adriana crawls under him, her tongue dragging up his balls before she licks where he’s stretching Yulia open. Maya whines, her fingers furious inside herself as she watches, her other hand pinching her nipple hard.
<<speech "Adriana">>"Yes—! Ruin her—! Ruin us all—!"<</speech>> Adriana moans, her tongue swirling over Yulia’s clit as $name pounds into her.
Yulia’s words dissolve into gibberish, her body convulsing as she comes, her cunt milking him. <<speech "Yulia">>"N-$name—! Da—! Blyat—! MORE—!"<</speech>>
Maya screams, her back arching as her own orgasm hits, her juices spilling over her fingers. <<speech "Maya">>"I-I need you next—! PLEASE—!"<</speech>>
The parasite roars in triumph.
Good. Now fill them all.
$name pulls out of Yulia, her cunt gaping as his cum spills out of her. He grips Maya by the hips, flipping her onto the desk, her ass slapping against the wood as he slams into her. Adriana crawls up, her mouth finding his, her tongue forcing its way in as she rides his thigh, her cunt grinding against him.
<<speech "Adriana">>"Breed us…"<</speech>> Adriana pants against his lips. <<speech "Adriana">>"Make us yours…"<</speech>>
Yulia collapses, her body twitching, her hand furiously working her clit as she watches them. <<speech "Yulia">>"I-I love you…"<</speech>> Her voice is broken, her mind gone. <<speech "Yulia">>"I love you so much—!"<</speech>>
Maya’s walls clench around him, her orgasm milking him as he unloads inside her. <<speech "Maya">>"YES—! GIVE IT TO ME—! ALL OF IT—!"<</speech>>
The parasite sings as their minds shatter, their bodies convulsing in unison.
Perfect. Now claim the rest.
<</if>>
<<case "Amber_Class_Standard">>
<<if _tier is 0 or _tier is 1>>
The art classroom is bathed in golden afternoon light, the scent of paint and clay thick in the air. Professor Amber stands by the easel at the front, her sleeves rolled up to her elbows, a smudge of charcoal on her cheek. She’s laughing at something Chloe said, her warm voice filling the room. Chloe lounges on a stool near the front, her legs swung over the side, a sketchbook balanced on her knees. Melody sits cross-legged on the floor near the window, her fingers tracing idle patterns in the dust on the windowsill, her expression distant but not unhappy.
$name pushes open the door, his eyes scanning the room. No Elsa.
Amber turns, her smile widening. <<speech "Amber">>"$name! What a surprise. Here to check on your $family?"<</speech>> She wipes her hands on her apron, leaving streaks of blue paint on the fabric.
Chloe grins, spinning her pencil between her fingers. <<speech "Chloe">>"She’s not here yet. Probably got held up in the library again."<</speech>> She tilts her head, her ponytail swinging. <<speech "Chloe">>"You could’ve just texted her, you know. She’s been glued to her phone lately."<</speech>>
Melody glances up, her dark eyes flicking to $name before darting away. <<speech "Melody">>"She said she had to finish something for her independent study…"<</speech>> Her voice is soft, almost lost under the hum of the room. She tucks a strand of hair behind her ear, her fingers lingering on the silver ring she always wears.
$name exhales, rubbing the back of his neck. <<speech "$name">>"She’s not answering her phone. I just wanted to make sure she didn’t forget about dinner."<</speech>> His voice is rough with worry—she’s been distant lately.
Amber’s expression softens. <<speech "Amber">>"She’s been working hard. But if she’s not here in the next ten minutes, I’ll give her a call."<</speech>> She steps closer, her hand brushing his arm—reassuring, sisterly. <<speech "Amber">>"You’re a good $familymale, $name. She’s lucky to have you."<</speech>>
Chloe smirks, nudging Melody with her foot. <<speech "Chloe">>"Yeah, yeah. Overprotective $familymale alert."<</speech>> She winks at $name. <<speech "Chloe">>"But seriously, she’s probably fine. She’s been in a mood lately, but you know how she gets when she’s working on something."<</speech>>
Melody’s fingers tighten around her pencil. <<speech "Melody">>"She’s been… quieter. But she’ll talk when she’s ready."<</speech>> Her voice is barely above a whisper, but there’s a firmness to it.
$name’s phone buzzes in his pocket. He pulls it out—Elsa. <<speech "$name">>"Speak of the devil."<</speech>> He answers, stepping toward the window for privacy. <<speech "$name">>"Hey, where are you? I was just in Amber’s class looking for you—"<</speech>> His voice drops to a murmur as Elsa’s voice filters through the phone, too quiet to hear.
Amber watches him, her hands twisting together. <<speech "Amber">>"Tell her to hurry up. We’ve got a critique in twenty minutes."<</speech>> Her voice is warm, but there’s an edge of concern beneath it.
Chloe stretches, arching her back. <<speech "Chloe">>"If she’s skipping, I call dibs on her snacks."<</speech>> She grins, but her eyes flick to $name, her expression softening. <<speech "Chloe">>"But seriously, if she’s not here soon, I’ll go find her."<</speech>>
Melody doesn’t say anything. She just listens to Elsa and $name's phone call with a fond smile.
<<elseif _tier is 2>>
The parasite pulses in $name’s chest, its tendrils coiling around his spine, heightening every sensation. The art classroom feels different—the air thicker, the scent of paint and clay intoxicating. Amber’s blouse is unbuttoned just enough to tease the curve of her breasts, her skirt clinging to her hips when she moves. Chloe’s tank top is snug, her nipples hard beneath the fabric, her legs crossed and squeezed tight. Melody’s sweater has slipped off one shoulder, her fingers twitching at the hem like she’s too warm, her cheeks flushed.
Amber looks up as $name enters, her lips parting, her tongue darting out to wet them. <<speech "Amber">>"$name…"<</speech>> Her voice is softer, breathier. <<speech "Amber">>"Looking for Elsa?"<</speech>> She steps closer, her hips swaying just a little more than usual. Her hand lifts, her fingers brushing his chest—accidentally, of course.
Chloe licks her lips, her eyes dark as she watches Amber’s fingers trail down $name’s arm. <<speech "Chloe">>"She’s not here yet. But you can… stay awhile."<</speech>> Her voice is a purr, her foot sliding up his calf under the table.
Melody gasps, her pencil snapping in her grip. She stares at the graphite dust on her fingers, her breath coming faster. <<speech "Melody">>"S-She’s probably in the library…"<</speech>> Her voice is a whisper, her thighs pressing together under her skirt.
$name’s breath hitches. The parasite whispers: They want you. Take them.
<<speech "$name">>"Have you seen her?"<</speech>> His voice is rougher, deeper.
Amber’s lips curl. <<speech "Amber">>"Not since this morning. But you’re welcome to wait."<</speech>> Her hand slides to his waist, her thumb hooking into his belt loop. <<speech "Amber">>"We were just discussing… the human form."<</speech>> Her gaze drops to his lips, then lower.
Chloe grins, her fingers tracing idle circles on her thigh. <<speech "Chloe">>"Yeah. Very educational."<</speech>> She stands, stretching in a way that presses her small tits against her top. <<speech "Chloe">>"You could help us. Firsthand reference and all."<</speech>>
Melody whimpers, her fingers digging into her thighs. <<speech "Melody">>"I-I saw her earlier…"<</speech>> Her voice is strained, her breath coming faster. <<speech "Melody">>"She was… fine."<</speech>> Her eyes flick to $name, then away, her cheeks burning.
His hand grips Amber’s hip, pulling her against him. She gasps, her body melting into his, her fingers clutching at his shirt. <<speech "$name">>"Professor…"<</speech>> His voice is a growl. <<speech "$name">>"You shouldn’t tease."<</speech>>
Chloe moans, her hand slipping between her thighs, her skirt riding up as she grinds into her own fingers. <<speech "Chloe">>"Fuck Elsa,"<</speech>> Chloe whispers, her tongue dragging up his neck. <<speech "Chloe">>"Stay with us."<</speech>>
Melody watches, her breath hitching, her fingers trembling as she touches herself through her skirt. <<speech "Melody">>"N-$name…"<</speech>> Her voice is a sob. <<speech "Melody">>"This isn’t… right…"<</speech>> But her hand doesn’t stop.
The parasite laughs.
<<elseif _tier is 3>>
The classroom is empty—or it should be. The blinds are drawn, the only light coming from the kiln, casting long shadows that make the easels look like altars.
Amber is on her knees before $name even fully enters the room, her blouse torn open, her bra pushed up to frame her heavy breasts. Chloe sits on the edge of a table, her skirt hitched up, her panties gone, her fingers buried inside herself as she whimpers. Melody is pressed against the wall, her legs trembling, her hand working between her thighs, her eyes wide and glazed.
<<speech "Amber">>"$name…"<</speech>> Amber breathes, her voice a moan. Her hands are already at his belt, her fingers fumbling in her haste. <<speech "Amber">>"We were talking about you…"<</speech>> Her tongue darts out, swirling over the head of his cock as she frees it. <<speech "Amber">>"About how good you’d taste…"<</speech>>
Chloe whines, her fingers squishing as she fucks herself. <<speech "Chloe">>"C’mon, Melody. Help me worship him."<</speech>> She grins, her voice rough, her free hand beckoning.
Melody whimpers, but she obeys, crawling forward on shaking limbs. <<speech "Melody">>"I-I shouldn’t…"<</speech>> Her voice is broken, but her mouth joins Amber’s as they worship his cock together.
$name groans, his hands tangling in their hair. <<speech "$name">>"Fuck—"*<</speech>> His hips jerk forward, his cock hitting the back of Amber’s throat. She gags, but her hands only tighten on his ass, pulling him deeper.
Chloe replaces Melody, her mouth stretching around him as she takes him to the root. <<speech "Chloe">>"Mmm—fuck, you’re huge…"<</speech>> She pulls back, her lips popping off the head. <<speech "Chloe">>"Bet Elsa never sucked you like this."<</speech>> She winks, before diving back in, her throat fluttering around him.
Amber’s hands roam, one slipping into her own panties, her fingers circling her clit as she chokes on his cock. <<speech "Amber">>"G-Good boy…"<</speech>> she gasps. <<speech "Amber">>"Let us take care of you…"<</speech>>
Melody watches, her breath hitching, her fingers furious inside herself. <<speech "Melody">>"This is wrong…"<</speech>> Her voice is a sob, but her free hand grips his thigh, her nails digging in.
<<else>>
The art classroom isn’t a classroom anymore. It’s a breeding den, the walls slick with condensation, the air thick with the scent of sex and submission. The parasite has rewritten them—mind, body, soul.
Amber is naked, her body marked with the parasite’s creeping veins, her tits swollen, her cunt dripping onto the floor. Chloe is bent over a table, her ass in the air, her pussy clenching around nothing, her moans slurred and desperate. Melody is spread on the professor’s chair, her legs hooked over the arms, her fingers stretching her cunt open in offering, her eyes empty of everything but need.
<<speech "Amber">>"N-$name…"<</speech>> Amber whines, crawling toward him, her nails scoring the floor. <<speech "Amber">>"We were supposed to be discussing art…"<</speech>> She giggles, the sound broken. <<speech "Amber">>"Now I just… need your cock…"<</speech>> Her hands grope at him, her mouth drooling in anticipation.
Chloe sobs, her hips rocking back, her ass jiggling. <<speech "Chloe">>"P-Please… I c-can’t think anymore…"<</speech>> Her voice is guttural, her usual cheerfulness gone. <<speech "Chloe">>"Just fuck me… Breed me…"<</speech>>
Melody spreads herself wider, her fingers plunging into her pussy. <<speech "Melody">>"I-I love you…"<</speech>> Her words are slurred, her eyes glazed. <<speech "Melody">>"F-Fill me up…"<</speech>>
$name grins—or rather, the parasite grins through him.
He slams into Chloe first, her tight cunt swallowing him whole as she screams, her nails scoring the table. Amber crawls under him, her tongue dragging up his balls before she licks where he’s stretching Chloe open. Melody whines, her fingers furious inside herself as she watches, her other hand pinching her nipple hard.
<<speech "Amber">>"Yes—! Ruin her—! Ruin us all—!"<</speech>> Amber moans, her tongue swirling over Chloe’s clit as $name pounds into her.
Chloe’s words dissolve into gibberish, her body convulsing as she comes, her cunt milking him. <<speech "Chloe">>"N-$name—! Fuck—! MORE—!"<</speech>>
Melody screams, her back arching as her own orgasm hits, her juices spilling over her fingers. <<speech "Melody">>"I-I need you next—! PLEASE—!"<</speech>>
The parasite roars in triumph.
Good. Now fill them all.
$name pulls out of Chloe, her cunt gaping as his cum spills out of her. He grips Melody by the hips, flipping her onto the table, her ass slapping against the wood as he slams into her. Amber crawls up, her mouth finding his, her tongue forcing its way in as she rides his thigh, her cunt grinding against him.
<<speech "Amber">>"Breed us…"<</speech>> Amber pants against his lips. <<speech "Amber">>"Make us yours…"<</speech>>
Chloe collapses, her body twitching, her hand furiously working her clit as she watches them. <<speech "Chloe">>"I-I love you…"<</speech>> Her voice is broken, her mind gone. <<speech "Chloe">>"I love you so much—!"<</speech>>
Melody’s walls clench around him, her orgasm milking him as he unloads inside her. <<speech "Melody">>"YES—! GIVE IT TO ME—! ALL OF IT—!"<</speech>>
The parasite sings as their minds shatter, their bodies convulsing in unison.
Perfect. Now claim the rest.
$name’s phone buzzes again—Elsa. He ignores it, his hands gripping Amber’s hips as he slams her onto the table beside Melody, his cock already hardening again.
<<speech "$name">>"Time for another lesson."<</speech>> His voice is not his own.
<</if>>
<<case "Staff_Room_Standard">>
<<if _tier is 0 or _tier is 1>>
The staff room has two kettles because of an argument nobody will explain, a sofa that has given up entirely, and a noticeboard with a rota on it from two years ago. It smells of instant coffee and the inside of a microwave.
Chanel has the good chair by the window with a stack of marking and a red pen she uses sparingly. Adriana is at the table with her laptop and a lunch she has been eating for an hour. Veruca is making tea for three people, two of whom did not ask for it.
$name is at the end of the table with a box of student files, sorting them into piles by a system Veruca explained to him once and he has mostly retained.
<<speech "Chanel">>(not looking up) "Your last essay was good."<</speech>>
<<speech "$name">>"You gave it a B."<</speech>>
<<speech "Chanel">>"It was a good B. Don't be greedy."<</speech>>
<<speech "$name">>"What stopped it being an A?"<</speech>>
<<speech "Chanel">>(now looking up) "You were right about everything and you didn't argue with yourself once. It reads like a person who has never been wrong. That's not analysis, that's a press release."<</speech>>
Adriana snorts into her lunch.
<<speech "Adriana">>"She said almost exactly that about my doctoral thesis."<</speech>>
<<speech "Chanel">>"I was right then as well."<</speech>>
Veruca puts a mug down beside Chanel without being noticed, then one beside Adriana, then one in front of $name. She has made his the way he takes it and neither of them mentions it.
<<speech "Veruca">>(quietly, sitting) "Have you got Ash's file in there?"<</speech>>
<<speech "$name">>"Should be. Why?"<</speech>>
<<speech "Veruca">>"She's been in detention twice this term and neither of them was for anything."<</speech>>
<<speech "Chanel">>"Detention is generally for something."<</speech>>
<<speech "Veruca">>"Not hers. Both were late work. She hands it in — she just takes it back again before the deadline, and then it's late, and then it's a detention."<</speech>>
The room goes quiet in a way it hadn't been a moment before. Adriana closes the laptop.
<<speech "Adriana">>"How long has that been happening?"<</speech>>
<<speech "Veruca">>"Since the start of term. It's in the file if you look at the dates rather than the reasons."<</speech>>
$name finds it, turns it round, and puts it in the middle of the table. The dates make a pattern the reasons entirely hide.
<<speech "Chanel">>(after a moment) "That's a good catch."<</speech>>
<<speech "Veruca">>(going pink) "It's just — it's the only thing I'm actually looking at, so."<</speech>>
<<speech "Adriana">>"Veruca. It's a good catch. Take the sentence."<</speech>>
<<speech "Veruca">>"…Thank you."<</speech>>
She takes it badly, the way she takes everything from adults, and busies herself with a teaspoon that does not need attention.
<<speech "$name">>"So what happens now?"<</speech>>
<<speech "Chanel">>"Now Veruca goes and sits with her for twenty minutes and doesn't mention any of this, and it quietly stops happening."<</speech>>
<<speech "Veruca">>(to her tea) "That's what I was going to do anyway."<</speech>>
<<speech "Chanel">>"I know. I'm telling the room so it's minuted somewhere."<</speech>>
The second kettle, which nobody has touched, clicks off by itself. Nobody comments on that either.
<<elseif _tier is 2>>
The staff room is close and sweet and the window has been open for an hour without helping. Three women are working through an afternoon in a haze none of them has thought to name.
Chanel's blouse is open two buttons past professional and her skirt has ridden up where she has crossed and recrossed her legs. She is still marking. The red pen is still moving.
<<speech "Chanel">>"This one's an A and she'll be insufferable about it."<</speech>>
<<speech "$name">>"Give it to her anyway."<</speech>>
<<speech "Chanel">>"Obviously I'll give it to her. I'm allowed to dread it."<</speech>>
He sits on the arm of her chair and puts a hand into her blouse, and Chanel adjusts her shoulder to give him a better angle without pausing the pen.
<<speech "Chanel">>"Her conclusion argues with her introduction and I don't think she noticed."<</speech>>
<<speech "$name">>"You said that's what you wanted."<</speech>>
<<speech "Chanel">>"I said I wanted it //deliberately//. Accidents get a B plus."<</speech>>
Adriana's dress is doing considerably less than it did this morning. She has her chair turned toward the room and her knees have drifted apart, and the fabric between them has a dark spreading patch she has not adjusted for.
<<speech "Adriana">>"I've got a seminar at four and I have read none of it."<</speech>>
<<speech "$name">>"What's it on?"<</speech>>
<<speech "Adriana">>"Ritual and — hm."<</speech>>
She stops. Her hand closes on the edge of the table. Whatever goes through her takes five or six seconds and she rides it out with her eyes shut and her mouth slightly open, and when it lets go she looks around the room with a small frown.
<<speech "Adriana">>"Sorry, I've completely lost it. What were we —"<</speech>>
<<speech "$name">>"Your seminar."<</speech>>
<<speech "Adriana">>"My seminar! Yes. Ritual and kinship."<</speech>>
She reopens the laptop. $name slides a hand up her inner thigh and she parts her knees a little further to let him, still scrolling.
Veruca is at the counter with her back to the room, and the cardigan has come off both shoulders and she has not put it back. She has been washing the same mug for a while. When $name comes up behind her and puts both hands on her hips she goes very still, and then leans back into him, and says nothing at all.
<<speech "$name">>"Veruca."<</speech>>
<<speech "Veruca">>"…Mm."<</speech>>
<<speech "$name">>"You've done that mug."<</speech>>
<<speech "Veruca">>"I know."<</speech>>
She keeps doing it. In the corridor two students go past arguing about a bus, and neither of them so much as glances through the glass.
<<elseif _tier is 3>>
The marking has gone on the floor. The good chair by the window has been turned to face into the room, and Chanel is not in it — she is on the carpet in front of it, on her knees, with her hair down and her mouth full.
She is unhurried and precise and appallingly good at it, and she keeps her eyes on his the entire time, which is somehow the most professorial thing about her.
<<speech "$name">>"You're not going to say anything?"<</speech>>
<<speech "Chanel">>(coming off him slowly) "I'm demonstrating rather than asserting. You should try it in an essay."<</speech>>
<<speech "$name">>"That's a B plus at best."<</speech>>
<<speech "Chanel">>"Then I'll revise."<</speech>>
Adriana is beside her with her dress round her waist, and she does not take turns so much as insinuate herself — a hand here, her mouth on the side of his shaft while Chanel has the head, the two of them meeting in the middle without any discussion at all.
<<speech "Adriana">>(warm, breathless) "This is much better than the seminar."<</speech>>
<<speech "$name">>"You're still going to the seminar."<</speech>>
<<speech "Adriana">>"I know. I'll be thinking about this in it."<</speech>>
Veruca has come away from the counter and is kneeling slightly behind the other two, cardigan off entirely, hands in her lap, waiting to be told.
<<speech "$name">>"Veruca. Come here."<</speech>>
She moves immediately. Whatever she is with adults, she is not that now — she takes him into her mouth with her eyes shut and a small grateful sound and stays there far longer than she needs to.
<<speech "Chanel">>(watching, quietly impressed) "She doesn't do anything by halves. She never has."<</speech>>
<<speech "$name">>"You knew that."<</speech>>
<<speech "Chanel">>"I've known that for eleven years. Nobody else in this building does."<</speech>>
Veruca surfaces just long enough to go a violent colour at being talked about, and then goes straight back down, and Adriana laughs against his hip and kisses the crease of his thigh.
The kettle nobody touched clicks off again.
<<else>>
The staff room has been finished with as a staff room. The rota is still on the noticeboard. The sofa that had given up has been given up on entirely and pushed aside, and there is a heap of marked essays in the corner that somebody knelt on.
Chanel is over the table, forearms flat, skirt gone. Adriana is on the sofa with her legs open and one hand busy, and Veruca is on the floor between them with her cheek against Chanel's calf, waiting.
<<speech "Chanel">>"Get on with it. I have a department meeting at five and I intend to be leaking through it."<</speech>>
<<speech "$name">>"You'll sit through a meeting like that?"<</speech>>
<<speech "Chanel">>"I'll //chair// it like that."<</speech>>
You take her hard from behind and she braces and swears once, quietly, in a way that eleven years of students would not recognise.
<<speech "Chanel">>"Yes — breed your professor, that's it, fill me and let me go and talk about timetables —"<</speech>>
Adriana slides down off the sofa and puts her mouth to where the two of them are joined, and Chanel's arms give out and she goes down onto her elbows.
<<speech "Adriana">>(surfacing, mouth wet) "She tastes of you already. She's been like this since lunch."<</speech>>
<<speech "$name">>"And you?"<</speech>>
<<speech "Adriana">>"I've ruined a chair. I don't care. Do me next and do it deep, I want to be carrying by the seminar."<</speech>>
She gets it bent over the arm of the dead sofa and she is loud, unashamedly, in a room with a corridor outside it.
Veruca last, because Veruca always waits. She lies back on the carpet among the essays and holds her own knees and looks up with an expression of complete uncomplicated need.
<<speech "Veruca">>"I've wanted this since the start of term."<</speech>>
<<speech "$name">>"You never said."<</speech>>
<<speech "Veruca">>"I don't say things. Please just breed me."<</speech>>
You do, and she cries out once and then holds on with both arms and both legs and does not let go until it is over.
Afterwards the three of them lie among the paperwork of their own careers, dripping and content, and the first bell for the next period goes off in the corridor and none of them moves.
<</if>>
<<case "Detention_Standard">>
<<if _tier is 0 or _tier is 1>>
The detention room is the old music room and still smells faintly of it under the floor polish. Eleven desks, spaced far enough apart that nobody can pass anything. A laminated card by the door: phones in the tray, no food, no talking, work or sit quietly. The radiator ticks. The clock above the door is ninety seconds fast.
Mia has the rota slot this week because somebody is off, and she has brought her own paperwork up with her, which tells you roughly how much of her attention the room is getting.
<<speech "Mia">>"Phone in the tray, Rae."<</speech>>
<<speech "Rae">>"It's off."<</speech>>
<<speech "Mia">>"In the tray."<</speech>>
Rae drops it in from a height. It's not loud enough to be worth saying anything about, which is the point of doing it that way.
$name came up with the afternoon registers and Mia told him to sit rather than walk back down, so he's on the end of the second row with nothing to do. Two reflection sheets went out at the start of the hour. Ash's is finished. Rae's is face down under her elbow with nothing on it.
The whole thing was a phone in Adriana's class. Rae had it out, got told about it, and said something back that she is not repeating in front of Mia. Ash was turned round in the next seat when it happened. It came out as //both of you//, and it went in the book as both of them, and that was fifteen seconds of a Tuesday.
<<speech "$name">>(low, to Ash) "You weren't even on your phone."<</speech>>
<<speech "Ash">>"…No."<</speech>>
<<speech "$name">>"So tell her that."<</speech>>
Ash does something with one shoulder that is smaller than a shrug and goes back to her notebook.
<<speech "Rae">>(from the back) "She's not going to."<</speech>>
<<speech "$name">>"You could tell her."<</speech>>
<<speech "Rae">>"I did tell her."<</speech>>
<<speech "$name">>"And?"<</speech>>
<<speech "Rae">>(putting on a voice) "I said //she wasn't doing anything, she was just sat there//, except I said it like //that//, so."<</speech>>
She goes back to the ceiling. It's not an apology and it isn't shaped like one.
<<speech "$name">>"Say it again properly tomorrow."<</speech>>
<<speech "Rae">>"Yeah."<</speech>>
<<speech "$name">>"You said that yesterday."<</speech>>
<<speech "Rae">>(pleased with herself) "Then I'm consistent."<</speech>>
<<speech "Mia">>"Rae. The sheet."<</speech>>
<<speech "Rae">>"I'm thinking about it."<</speech>>
<<speech "Mia">>"You've had forty minutes."<</speech>>
<<speech "Rae">>"I'm a slow thinker."<</speech>>
Mia looks at her for a second, decides it isn't worth the next three moves, and goes back to her own folder. Rae registers the win and doesn't do anything with it, because there's nothing to do with it in a room with eleven desks and no phone.
She starts kicking the leg of the desk in front of her. Not hard. Just a rhythm.
<<speech "Mia">>(without looking up) "Stop that."<</speech>>
It stops. It starts again about two minutes later, slightly slower.
$name can read Ash's reflection sheet from where he's sitting, upside down. Box one, what happened. Box two, who was affected. She has written that she was disruptive in class.
<<speech "$name">>"That's not what happened, though."<</speech>>
<<speech "Ash">>"It's easier."<</speech>>
<<speech "$name">>"Easier than what?"<</speech>>
She doesn't answer that. She turns the page over and carries on with the drawing she has been doing all hour, which is a hand, five or six times, each one worse than the one before it.
<<speech "Rae">>"That's how they get you, that. You write down you did it and then you did it."<</speech>>
<<speech "$name">>"You could have not got her in here."<</speech>>
<<speech "Rae">>"I know."<</speech>>
She says it the way you'd agree with the weather. Someone goes past in the corridor and doesn't look in.
<<speech "Mia">>"Twenty minutes. Sheets on my desk before you go, both of you."<</speech>>
<<speech "Rae">>(groaning at the ceiling) "//Twenty.//"<</speech>>
<<elseif _tier is 2>>
The air in the room has weight to it. Not heat — the radiator is doing what it always does — but something close and sweet sitting at the back of the throat, and none of the three of them have said a word about it.
Mia's cardigan is over the back of her chair and her chair is turned out from the desk, away from her folder, knees apart under the skirt. One more button than she'd have chosen this morning. She's flushed across the cheeks and still working through the page in exactly the voice she uses for everything.
<<speech "Mia">>"Half of these are the same four students. It's the last period of the day, that's all it is."<</speech>>
<<speech "$name">>"Have you told anyone that? Because they're going to keep sending you the same four kids until somebody moves the lesson."<</speech>>
<<speech "Mia">>"Twice. It's not a popular explanation."<</speech>>
<<speech "$name">>"No, it's boring. Nobody wants the boring one."<</speech>>
He's come round behind her chair. He puts a hand flat on her collarbone and she tips her head back against him without stopping, her throat moving under his palm, and finds her place on the page again.
Rae has her shirt knotted up under her ribs and her tie gone entirely, used to pull her hair off her neck. Her boots are off the desk for the first time all hour because she can't keep still, and her thighs press and release against each other in a rhythm she isn't tracking.
<<speech "Rae">>"And the thing is I //would// have said it properly, I just —"<</speech>>
She stops. Her mouth is open on the next word and it doesn't arrive. Colour comes up her throat, her hand closes on the edge of the desk hard enough to go white across the knuckles, and her hips roll once against the chair, slow, nothing to do with her. Four seconds, maybe. Then she blinks and frowns at the blank reflection sheet.
<<speech "Rae">>"…What was I on about?"<</speech>>
<<speech "$name">>"Something you were going to say properly."<</speech>>
<<speech "Rae">>"Doesn't matter."<</speech>>
She reaches down and presses the heel of her hand between her legs through the jeans, briefly, the way you'd deal with an itch on your arm in a room full of people, and goes back to the ceiling tiles.
Ash's cardigan has come off both shoulders and stayed there. Sleeves pulled over her hands, drawing very fast and pressing far too hard. When $name sits on the edge of her desk she leans over without any hesitation and rests her cheek against his thigh, and keeps going.
<<speech "Ash">>"…That's nice."<</speech>>
<<speech "$name">>"Don't stop on my account. You're nearly at the bottom of the page."<</speech>>
<<speech "Ash">>"I am."<</speech>>
She is. The thing on the page stopped being a hand a while ago and she hasn't looked up to check.
<<speech "Mia">>"Ten minutes."<</speech>>
<<speech "$name">>"Nobody's going anywhere. Rae hasn't written a word and you've stopped marking."<</speech>>
<<speech "Mia">>(agreeably, still reading) "No. Apparently not."<</speech>>
<<elseif _tier is 3>>
The door isn't locked. It could be. Nobody has brought it up.
Rae gets there first, which is Rae all over. She comes up the aisle, drops to her knees in front of him in the middle of the room with her hair still tied off her neck with her own tie, and looks up grinning.
<<speech "Rae">>"Put this on the sheet."<</speech>>
<<speech "$name">>"Which box?"<</speech>>
<<speech "Rae">>"Two. //Who was affected.//"<</speech>>
Then she takes him in her mouth and makes a production of it — noisy, sloppy, deliberately graceless, gagging herself once on purpose and grinning around it while she recovers. She's soaked through the jeans doing it.
Mia comes over from her desk with her blouse hanging open and kneels down beside her without any particular hurry.
<<speech "Mia">>"Slower."<</speech>>
<<speech "Rae">>(off him, wet) "Why?"<</speech>>
<<speech "Mia">>"Because you're doing it to be seen doing it."<</speech>>
She takes over, and it's a different thing entirely — unhurried, eyes up, her mug of tea going cold on the desk above her exactly the way it has every hour she's ever sat in this room.
<<speech "$name">>"Your folder's still open on the desk. You were halfway down a page."<</speech>>
<<speech "Mia">>(pulling off) "It'll keep."<</speech>>
Ash hasn't moved. She's at her desk with the cardigan gone and one hand out of sight under it, watching over the top of the notebook, breathing far too quickly.
<<speech "$name">>"Ash. You've been sat there the whole time. Come here."<</speech>>
She comes. She kneels between the other two without a word and takes him carefully, almost apologetically, and then makes a sound she clearly wasn't planning on.
<<speech "Rae">>(delighted) "//There// she is."<</speech>>
<<speech "Ash">>(mortified, not stopping) "Don't — don't say anything —"<</speech>>
<<speech "$name">>"She's not saying anything. Nobody in this room is saying anything."<</speech>>
<<speech "Mia">>"Breathe through your nose."<</speech>>
The radiator ticks. The corridor stays empty. The three of them work at him in turns and the clock above the door goes round ninety seconds fast and nobody looks at it.
<<else>>
The detention room has stopped being a room in a school. The desks are shoved back against the walls, the blind is down over a corridor nobody uses any more, and the smell has got into the soft parts of the room and stayed there.
Mia is bent over the front desk with her folder still open underneath her, skirt gone, slick to the knee. Rae is on the floor beside her with her legs open and two fingers working and her eyes up. Ash is in the front row seat with nothing on at all, notebook open beside her, nothing drawn in it for a long time.
<<speech "Mia">>(calm, and the calm is the worst of it) "Whenever you're ready."<</speech>>
<<speech "$name">>"You're always ready. You were ready before I came through the door."<</speech>>
<<speech "Mia">>"Yes. That's rather the point of me now."<</speech>>
You take her over the desk and she braces on her forearms and moans low and steady while the paperwork goes off the edge a sheet at a time. Both reflection sheets go with it. She keeps narrating between breaths for a while, still doing the job, right up until she doesn't.
<<speech "Mia">>"Four students, the same four every — ah — and none of it //matters//, does it —"<</speech>>
<<speech "$name">>"No. None of it does. You can leave the folder open."<</speech>>
<<speech "Mia">>"No. Breed me instead. Better use of the hour."<</speech>>
Rae crawls over without being asked and puts her mouth where the two of you meet, and Mia's voice breaks in the middle of a word.
<<speech "Rae">>(surfacing, filthy and pleased) "God, she's dripping. Harder, I want it on my face."<</speech>>
<<speech "$name">>"You'll get your turn. Stay where you are and open your mouth."<</speech>>
<<speech "Rae">>"I'd do the whole thing again, by the way. All of it. Best afternoon of my life."<</speech>>
When you finish in Mia she stays folded over her own folder, letting it run out of her onto the desk, in no hurry at all. Rae takes her place the second there's room, face down, back arched, and goes off on the third stroke, loud, with none of the front she's had up all hour.
Ash waits. She always waits. When you get to her she's shaking and open and she says the only full sentence she's said all afternoon.
<<speech "Ash">>"Please put it in me."<</speech>>
<<speech "$name">>"Say it again."<</speech>>
<<speech "Ash">>"Please — fill me up. All of it. I want it to take."<</speech>>
Afterwards the three of them stay where they are on the floor of the detention room, leaking, patient, waiting to be used again, and the radiator goes on ticking every forty seconds as though nothing in the building has changed.
<</if>>
<<case "Student_Council_Standard">>
<<if _tier is 0 or _tier is 1>>
The Student Council office is the tidiest room in the building and everybody knows it, which is at least half the point. There is a long table, a whiteboard covered in three different handwritings, and a window that looks out over the car park and catches the last of the afternoon.
The room smells of dry-wipe marker and the cheap coffee from the machine by the staff room, which Gabbie fetches four cups of and drinks three.
Adria is at the head of the table with the charity fair budget in front of her and the specific stillness of somebody who has been staring at the same column for eleven minutes. Jade has a laptop open and eight tabs of nothing anybody asked for. Gabbie is at the whiteboard adding a fourth colour.
<<speech "Adria">>"The numbers work. They only work if nobody gets ill and nothing rains."<</speech>>
<<speech "$name">>"So they don't work."<</speech>>
<<speech "Adria">>(not looking up) "Thank you, that's very helpful."<</speech>>
<<speech "$name">>"I'm serious. What's the actual float?"<</speech>>
<<speech "Adria">>"Two hundred and eleven."<</speech>>
<<speech "$name">>"That's not a float, that's a rounding error."<</speech>>
<<speech "Jade">>(without looking up) "That's what I said on Tuesday and got told I was being negative."<</speech>>
<<speech "Adria">>"You //were// being negative. You presented it as a slide."<</speech>>
<<speech "Jade">>"It was a good slide."<</speech>>
Gabbie caps a marker with her teeth and turns round.
<<speech "Gabbie">>"Okay but what if — hear me out — what if the posters were //bigger//."<</speech>>
<<speech "Jade">>"That's not a plan, that's a size."<</speech>>
<<speech "Gabbie">>"It's a plan with a size in it!"<</speech>>
$name pulls the budget sheet across the table and turns it round to look at it properly. Adria lets him, which she would not let most people.
<<speech "$name">>"You've costed the marquee twice."<</speech>>
There is a pause of exactly the right length.
<<speech "Adria">>"…Show me."<</speech>>
He shows her. It is on two lines, once under equipment and once under venue, and it is a hundred and forty pounds, and it is the difference between a plan that survives rain and one that doesn't.
<<speech "Jade">>(leaning over, genuinely pleased) "Oh, that's excellent. That's the whole gap."<</speech>>
<<speech "Adria">>"I've read this eleven times."<</speech>>
<<speech "$name">>"That's why you didn't see it."<</speech>>
Adria sits back. She takes a moment to be annoyed and then visibly decides not to be, which is a thing she has taught herself to do and it still shows.
<<speech "Adria">>"Right. Gabbie, the posters can be bigger."<</speech>>
<<speech "Gabbie">>(both fists up) "//Yes.//"<</speech>>
<<speech "Jade">>"On the condition that the numbers go on them."<</speech>>
<<speech "Gabbie">>"Numbers are ugly."<</speech>>
<<speech "Jade">>"Numbers are persuasive."<</speech>>
<<speech "Gabbie">>"Then they can be ugly in the corner."<</speech>>
Adria writes something on the corner of the sheet and slides it back to $name without comment, which from her is roughly a commendation. Outside, a car alarm goes off in the car park and stops again, and nobody in the room looks up.
<<elseif _tier is 2>>
The office is warmer than the corridor and it has nothing to do with the radiator. There is a sweetness in the air that clings, and the three of them have been breathing it for an hour without once remarking on it.
Adria's blouse is unbuttoned to the third button and she has stopped noticing when it gapes. She is still working — the budget is still in front of her, the pen is still moving — and her thighs are pressed together hard under the table.
<<speech "Adria">>"If we move the marquee line we free a hundred and forty."<</speech>>
<<speech "$name">>"What would you do with it?"<</speech>>
<<speech "Adria">>"Contingency. Boring answer."<</speech>>
<<speech "$name">>"Correct answer."<</speech>>
He stands behind her chair. His hand goes under the table and up her skirt and she is soaked through, and she reaches over and turns the page with her other hand as if the two things are unrelated activities happening to different people.
<<speech "Adria">>"Boring answers are how the fair happens at all."<</speech>>
Gabbie is at the whiteboard in a cropped hoodie and a skirt that is functionally decorative, and she is bouncing on the balls of her feet the way she always does.
<<speech "Gabbie">>"$name! Come look, I did the thing with the corner numbers —"<</speech>>
He comes and looks. He also puts a hand on her backside and squeezes, and Gabbie carries straight on pointing at the board with the marker.
<<speech "Gabbie">>"— see, ugly, but in the //corner//, so Jade can't —"<</speech>>
She stops. Her arm stays up. Her whole body goes rigid for three or four seconds, mouth slightly open, colour flooding up her neck, and the marker slips out of her fingers and rolls under the table.
<<speech "Gabbie">>(blinking, high and confused) "…Sorry. What was I — what was I saying?"<</speech>>
<<speech "$name">>"The corner."<</speech>>
<<speech "Gabbie">>"The corner! Right. Yes."<</speech>>
She picks up a different marker and keeps going.
Jade has not moved from the laptop. Her sheer button-up is doing very little and she has one leg drawn up onto the chair, and she is scrolling with two fingers while the other hand rests high on her own thigh and stays there.
<<speech "Jade">>"I've found the comparison data. Three schools, same size, same fair."<</speech>>
<<speech "$name">>"And?"<</speech>>
<<speech "Jade">>"And we're underselling by about forty per cent."<</speech>>
He reaches down the front of her shirt and rolls her nipple between two fingers. Jade's breath catches — audibly, once — and she keeps reading off the screen without adjusting anything.
<<speech "Jade">>"Forty. Which is — which is a lot, actually, that's a lot."<</speech>>
<<speech "$name">>"Put it in the slide."<</speech>>
<<speech "Jade">>"It's already in the slide."<</speech>>
The car park empties itself outside. Adria turns another page.
<<elseif _tier is 3>>
The whiteboard still has the fair on it. Somebody has knocked the coffee over and nobody has dealt with it.
Adria is on her knees at the head of the table where she chairs every meeting, blouse open, hair coming out of the clip, and she has your cock in her mouth and she is going about it with the same terrifying focus she brings to a budget. She does not rush. She does not come up for approval.
<<speech "$name">>"You're organising this."<</speech>>
<<speech "Adria">>(off him, wet, matter-of-fact) "Somebody has to."<</speech>>
<<speech "$name">>"Who's next, then?"<</speech>>
<<speech "Adria">>"Gabbie, because she'll combust otherwise."<</speech>>
<<speech "Gabbie">>"I //will//."<</speech>>
She drops down the second she's named, enthusiastic to the point of clumsy, and takes far too much immediately and has to back off coughing and laughing at herself.
<<speech "Gabbie">>(recovering, delighted) "Okay — okay, I've got it, I've got it —"<</speech>>
<<speech "$name">>"Slow down."<</speech>>
<<speech "Gabbie">>"I don't know how to do that."<</speech>>
She doesn't. She goes back in with everything she has and makes an appalling amount of noise about it, and Adria watches with an expression that is almost fond.
Jade comes last and comes prepared, because she is Jade. She kneels, considers, and then does something with her tongue on the underside that makes your hand go into her hair involuntarily.
<<speech "Jade">>(pulling off, insufferably pleased) "I read about that."<</speech>>
<<speech "$name">>"Of course you did."<</speech>>
<<speech "Jade">>"I read about a lot of things. You've been getting the abridged version."<</speech>>
<<speech "Adria">>"Don't let her monologue. She'll do it all afternoon."<</speech>>
They work him in a rotation that Adria is somehow still running, one hand raised each time she wants a swap, and the three of them take him apart on the floor of the office with the fair posters looking down from the wall.
<<else>>
The Student Council office has been given over entirely. The long table has been cleared by the simple method of pushing everything onto the floor, and the budget is somewhere under the whiteboard with a footprint on it.
Adria is face down on the table with her arse up, which is where she puts herself now without being asked. Gabbie is sprawled on the chairs with her legs over the arms, dripping onto the upholstery, waiting her turn and not waiting quietly. Jade is standing, one foot on a chair, working herself with two fingers and watching everything.
<<speech "Adria">>"Item one. Me."<</speech>>
<<speech "$name">>"You've been thinking about the order."<</speech>>
<<speech "Adria">>"I always think about the order. Item one. //Please.//"<</speech>>
You give it to her hard and she takes it with her cheek flat on the table, and the first thing she does is start counting the strokes out loud until she loses the number somewhere in the twenties.
<<speech "Adria">>"— breed me, breed me, put it in me, I've kept it empty all —"<</speech>>
<<speech "$name">>"All what?"<</speech>>
<<speech "Adria">>"All week. All of it. For this."<</speech>>
Gabbie can't wait and doesn't. She climbs onto the table beside Adria, face down in the same posture, hands stretched out flat.
<<speech "Gabbie">>"Me too, me too, do me next, I want to match her —"<</speech>>
<<speech "Jade">>(from the chair, thick and unhurried) "She means she wants to be pregnant at the same time as Adria."<</speech>>
<<speech "Gabbie">>"That's what I said!"<</speech>>
<<speech "Jade">>"You said //match//."<</speech>>
<<speech "Gabbie">>"Same thing!"<</speech>>
You finish in Adria and she stays down, spreading her knees to keep it in, and then you take Gabbie who comes almost immediately and keeps going anyway, loudly, until her voice gives out.
Jade waits until last and then bends herself over the head of the table, deliberately, in the chair Adria uses.
<<speech "Jade">>"Here. This one. I want it to be this one."<</speech>>
<<speech "$name">>"Why?"<</speech>>
<<speech "Jade">>"Because I've argued at this table for two years and I'd rather be bred over it."<</speech>>
Afterwards the three of them stay draped across the furniture of their own office, leaking onto the papers, and the fair posters are still on the wall, and the meeting is technically still in session.
<</if>>
<<case "Mia_Class_Before">>
<<if _tier is 0 or _tier is 1>>
Ten minutes before Mia's lecture and the room is half full—enough people to be loud, not enough to disappear into. The air carries the ordinary smells of university: paper, coffee, the faint chemical sweetness of highlighter ink, someone's perfume applied too generously three rows back.
Jade has colonized the second row with the efficiency of a minor government. Her laptop is open but dark—she prefers paper for thinking—surrounded by three color-coded highlighters and a lever-arch file fat with annotated readings. She sits with her back not quite touching the chair, spine straight, long black hair pushed behind her ears, her blouse buttoned to the collar. She is not unkind. She is simply never uncertain in public, and that reads to most people as the same thing. She is on student council with Adria, and where Adria commands, Jade arrives having already dismantled the proposal in her head.
Rae enters four minutes late, her jacket slung over one shoulder, her boots scuffing deliberately against the floor. She surveys the room with the lazy assessment of someone who has spent more time in punishment than in class, her sharp eyes landing on Jade's territory. She takes the seat directly in front of her—deliberate, provocative, a choice rather than a necessity.
Jade's pen stops. She does not look up immediately. She counts.
<<speech "Jade">>"There are thirty-eight working seats in this room."<</speech>>
<<speech "Rae">>"And you know the exact number, which is the whole problem with you."<</speech>>
Rae says it comfortably, without turning, folding herself down until she's more lying in the chair than sitting. She has been in detention four times this term. Twice for things she genuinely did; twice for saying something true to a member of staff who would rather she hadn't. She wears her rebellion like a scent—present, unmistakable, slightly dangerous.
<<speech "Jade">>"It's called paying attention."<</speech>>
<<speech "Rae">>"It's called counting chairs, Jade. There's a difference between attention and compulsion."<</speech>>
<<speech "$name">>"To be fair to her, she's the reason this room got rebooked when the projector died."<</speech>>
<<speech "Rae">>"To be fair to //me//, nobody asked her to."<</speech>>
<<speech "Jade">>"//Some// of us have to know how many seats there are, because //some// of us get asked to sign off on room bookings—"<</speech>>
<<speech "Rae">>"And there it is."<</speech>>
Caprice sits on the end of the row, her boots up on the seat in front, her sketchbook balanced on her knee. She wears an oversized cardigan that swallows her small frame, her hair dyed an unnatural shade that changes weekly—this week, a muted violet. She does not look up from what she's drawing, her pencil moving in short, precise strokes.
<<speech "Caprice">>"Four minutes."<</speech>>
<<speech "Jade">>"Four minutes //what//."<</speech>>
<<speech "Caprice">>"Since she sat down. You usually manage to argue for six."<</speech>>
She turns her sketchbook round without ceremony. There's a tally in the margin, eleven marks deep, dated. It is the only thing on the page—no drawings, just the record of Jade and Rae's conflicts, documented with the dry humor of a librarian who has seen everything and expects to see it again.
<<speech "Jade">>"You're keeping //score//?"<</speech>>
<<speech "Caprice">>"Since the start of term. It's the most consistent output I've produced all year."<</speech>>
<<speech "Rae">>"She's not wrong. She hasn't handed in an essay since the first week."<</speech>>
<<speech "$name">>"Two essays written, none handed in. That's worse than not writing them."<</speech>>
<<speech "Caprice">>"It's a different //kind// of worse. I'd like that on the record."<</speech>>
You take the seat beside Jade. She moves the lever-arch file off it without being asked—a small courtesy, significant because she does not offer space easily. Rae registers this from the row in front without appearing to move, her sharp eyes catching everything.
<<speech "Rae">>"Nobody else gets the file moved."<</speech>>
<<speech "Jade">>"He's on the group project."<</speech>>
<<speech "Rae">>"So am I. Mine's the section you still haven't read."<</speech>>
<<speech "Jade">>"You're //nominally// on the group project."<</speech>>
<<speech "$name">>"She sent the whole second section on Sunday. Referenced properly, under the word count, before either of us had opened the brief."<</speech>>
Jade turns and looks at you. It is a particular expression—she is genuinely good at arguing, and she has just been handed a fact she cannot dispute. There is a half-second where you can watch her decide whether to concede it, her intelligence warring with her certainty.
<<speech "Jade">>"…It was a good section."<</speech>>
<<speech "Rae">>"//Say that again//—"<</speech>>
<<speech "Jade">>"It was adequately researched and I'm not saying it twice."<</speech>>
<<speech "$name">>"Twelve of them. Does Mia know you're doing that in her lectures?"<</speech>>
<<speech "Caprice">>"Mia contributed a data point once. Twelfth mark, by the way."<</speech>>
Down the corridor, Mia gets caught by a student. The lecture will start eight minutes late, which it does every week. Jade will note the time in the corner of her page, which she does every week. The room breathes with ordinary tension—rivalry, sarcasm, the small wars of university life. Nothing is wrong. Everything is normal. The parasite sleeps.
<<elseif _tier is 2>>
The room fills the way it always does—forty-odd people, coats over seat backs, the noise of a hundred conversations that have nothing to do with the module. But the air is different today. Thicker. Warmer. A sweetness that clings to the back of the throat, barely noticeable, then unmistakable.
The seat beside Jade is clear before you're through the door. She has been turned toward the aisle for some minutes, her long black hair falling forward to hide her face, and when she sees you something drops out of her shoulders that she would deny under oath.
<<speech "Jade">>"You're late."<</speech>>
<<speech "$name">>"By two minutes."<</speech>>
<<speech "Jade">>"I know exactly how late you are, that's not the—"<</speech>>
She stops. Hears it—the need in her own voice, the desperation. She straightens a highlighter that did not need straightening, her fingers trembling.
Then she does something odd. She opens the lever-arch file to a section at the back—not the module, not the project—and turns it towards you about four inches, then thinks better of it and turns it back. Her blouse is unbuttoned to the third button, her collarbone visible, her skin flushed.
<<speech "$name">>"What's in the back of the file, Jade? That's not the module."<</speech>>
<<speech "Jade">>"Nothing. It's—I've been keeping notes."<</speech>>
<<speech "$name">>"Notes on what? You've got four pages of something in there."<</speech>>
<<speech "Jade">>"On //this//."<</speech>>
She says it too fast, immediately regrets the volume. Rae, in the row in front, has turned round—she turned round three weeks ago and has not turned back—and is watching the pair of you with her chin on her forearm. Her jacket is off, her tank top thin enough to show her nipples hard against the fabric, her jeans unbuttoned at the top.
<<speech "Rae">>"Show him. Go on."<</speech>>
<<speech "Jade">>"It's not finished."<</speech>>
<<speech "Rae">>"It's a list of times, Jade. It's not a thesis."<</speech>>
It is, in fact, a list of times. Two columns in Jade's small precise handwriting, four pages of it, going back to the first week of term. Dates on the left. On the right, a number and a single letter—J, R, C—and once or twice a scribbled note in the margin: mid-sentence, no warning, lasted approx 4s.
<<speech "$name">>"You've been logging them. Dates, durations, who it happened to—since the first week of term."<</speech>>
<<speech "Jade">>"Somebody has to. Nobody else in this room seems remotely bothered that we all keep—"<</speech>>
She loses it there. It arrives exactly the way her own notes describe: no warning, mid-sentence, her breath stopping and her spine locking and her hand closing hard enough on your forearm to leave four white marks. Her pupils blow wide. She flushes to the collarbones, her hips bucking slightly against the seat, a small gasp escaping her that she cannot control. It lasts four seconds. When it lets her go, she is panting, her blouse gaped open further, her hand still gripping you.
Nobody in the surrounding thirty people looks up. The air over these four seats is thick and sweet and hangs about four rows deep; a girl two along keeps shifting and rereading the same line, and the boy in front has been fanning himself with a handout for ten minutes, and neither of them could tell you why.
Jade, when she can, picks up the pen. Writes the time. Writes J.
<<speech "$name">>"Jade, you've just written down the time it happened while it was still happening."<</speech>>
<<speech "Jade">>"It's data."<</speech>>
<<speech "Rae">>"Mine are about eleven minutes apart. You can put that in your file, I've stopped bothering."<</speech>> She shifts, her jeans slipping lower, her hand drifting to her own thigh, tracing patterns. <<speech "Rae">>"I know it isn't normal. I just don't mind."<</speech>>
That lands harder than any of the arguing does, and Jade doesn't have anything for it, and her hand is still on your arm, and she doesn't move it away.
Caprice hasn't spoken in ten minutes. She has been drawing—glance up, draw, glance up—and when you catch her at it she doesn't look away or make a joke, which is the actual tell. Her cardigan is gone, her vintage dress straps fallen off both shoulders, her pale skin marked with faint dark tracery at her throat. She turns the page over slowly, holding your eye the whole time, her cheeks burning, her dry humor silenced into something desperate.
<<speech "Caprice">>"Don't ask."<</speech>>
<<speech "$name">>"I hadn't."<</speech>>
<<speech "Caprice">>"You were going to, and I'd have shown you, and then I'd have had to think about the fact that I wanted to."<</speech>> Her hand is under her dress, moving slowly, her artist's fingers now dedicated to her own pleasure. <<speech "Caprice">>"I've been drawing you. Since the start of term. Hundreds of pages. I can't stop."<</speech>>
Rae turns fully now, climbing over the back of her seat to sit on the desk in front of Jade, her legs spread slightly, her tank top riding up. <<speech "Rae">>"Eleven minutes. Want to check my data, researcher?"<</speech>>
Jade looks up at her—rival, antagonist, the person she argues with most—and her eyes fix on Rae's mouth, her flushed skin, her obvious arousal. The scientific detachment is cracking. The data is becoming desire.
<<speech "Jade">>(whispering) "I can't. I can't think. Every time I try to analyze—"<</speech>>
<<speech "Rae">>"Then stop analyzing."<</speech>> She reaches out, takes Jade's hand—the one that isn't gripping your arm—and places it on her own thigh, hot through the denim. <<speech "Rae">>"Just feel it. I've been feeling it since week three. It's better than fighting."<</speech>>
Jade's hand stays. Her fingers twitch. The file lies open, forgotten, as the room breathes with new corruption, the data becoming experience, the research becoming submission.
<<elseif _tier is 3>>
Twelve minutes to the lecture. The room fills with the murmur of forty students settling, laptops opening, the rustle of handouts. The air is thick—sweet, musky, wrong—but nobody remarks on it anymore. The back four rows have become a hazy territory where the parasite's pheromones pool, where concentration falters and pens drop and nobody picks them up.
Jade still sits in the second row, but her empire has shrunk to the space of her own chair. The lever-arch file lies open on her desk, not at the module notes but at the back section—nine pages now, her small precise handwriting degrading into loops and scratches. She's stopped logging times. She's stopped logging anything coherent. The last entry reads: "Because—" and nothing after.
She wears her blouse unbuttoned to the third button, her bra visible through the gap, her skirt hiked higher than she'd ever have allowed at the start of term. She keeps adjusting it, forgetting, adjusting again. Her long black hair, usually pushed back so precisely, falls forward to hide her flushed face.
Rae sits in front of her, but she's twisted around completely, her chin on her forearm, her detention-hardened eyes locked on you with a hunger that has nothing to do with rebellion anymore. She wears her detention clothes—ripped jeans, a tank top—but the jeans are unbuttoned, the tank pulled down to expose her collarbone, her shoulder, the swell of her breast. She's been fanning herself with a handout for ten minutes, the motion hypnotic, mindless.
<<speech "Rae">>"You've been staring at that file for eleven minutes, Jade. Write something or close it."<</speech>>
<<speech "Jade">>(her voice tight, controlled cracking) "I can't. I can't think. Every time I try to—"<</speech>> She stops. Her breath catches. Her spine locks. The wave hits her—pheromones thickening in her throat—and she grips the desk edge until her knuckles whiten. When it releases her, she's panting, her blouse gaped open further, her nipples hard and visible through the fabric.
<<speech "Rae">>"There it is. Fourth time since you sat down."<</speech>> She doesn't mock. She states. She's beyond mocking now. <<speech "Rae">>"You should stop pretending you're going to figure it out. I did. Week three."<</speech>>
Caprice appears beside them, silent, her sketchbook under her arm. She wears her library clothes—oversized cardigan, vintage dress—but the cardigan is gone, the dress straps fallen off one shoulder, her pale skin marked with dark veining that pulses at her throat. She hasn't drawn in an hour. She's been watching, her dry humor reduced to breathless need.
<<speech "Caprice">>"Move."<</speech>>
<<speech "Rae">>"Get your own."<</speech>>
<<speech "Caprice">>"There's one of him. Three of us. This was always the arrangement."<</speech>>
She says it without sarcasm. The aloofness has burned off, leaving only directness. She drops to her knees in the aisle, right there in the lecture hall, her dress pooling around her, her hands already at your belt. Her sketchbook falls, forgotten, pages scattering—hundreds of drawings, all the same subject, degrading from careful study to frantic scribbles to blank pages.
Rae follows without hesitation, sliding down between the seats, her rebellious nature transformed to desperate service. She takes him with her mouth before he's fully free, greedy, unbothered by the forty people three rows forward, unbothered by the lecturer's desk, unbothered by anything but the need to taste, to serve, to submit.
<<speech "Jade">>(whispering, her hand over her mouth) "There are—there are forty people—"<</speech>>
<<speech "Rae">>(muffled, pulling back with a gasp) "Forty-one. Count again."<</speech>> She goes back down, her tongue working, her eyes rolling back.
Caprice shares the space with her, the two of them working in tandem—Rae fast and desperate, Caprice slow and deliberate, her artist's hands now dedicated to stroking, cupping, worshipping. She looks up constantly, confirming the reference, her cheeks burning, her sarcasm silenced into moans.
Jade stays in her seat. Upright. Both feet flat. Her hands on the desk either side of the file, and she hasn't written anything for eleven minutes. She's shaking so hard the pen has rolled to the edge and fallen, and she doesn't pick it up.
<<speech "$name">>"You don't have to."<</speech>>
<<speech "Jade">>(her voice breaking, the debater reduced to stuttering) "I know I don't have to. That's the—the whole problem—if somebody were making me I could—"<</speech>>
<<speech "$name">>"Then you could write it down and it would be somebody else's fault. You could keep the version of yourself that reads the paperwork."<</speech>>
<<speech "Jade">>"//Yes.//"<</speech>>
It comes out as a sob. She looks at the file—nine pages of careful research, her identity as the organized one, the prepared one, the one who knows how many seats are in every room—and then she closes it with both hands. Deliberately. Finally.
She gets down onto the floor of the lecture hall, her blouse falling open completely, her skirt riding up to show she wears no underwear, her long black hair tangling with Rae's as she joins them.
<<speech "Rae">>(pulling back, grinning, still herself) "There she is."<</speech>>
<<speech "Jade">>"Don't."<</speech>>
Jade is, once she stops holding the line, by a considerable distance the most thorough of the three. She takes him deep immediately, her researcher's dedication turned to learning every inch, every response. She uses her hands precisely, her tongue deliberately, her confidence transformed from intellectual to physical. She doesn't come up for air. She doesn't hesitate. She simply applies herself, the way she applies herself to everything, until her eyes water and her throat works and she's gasping around him.
<<speech "Caprice">>(watching, her hand between her own legs) "She's going to chart this later. In her head. The angle. The duration."<</speech>>
<<speech "Rae">>(laughing, breathless) "Let her. It's data."<</speech>>
They work him together until he finishes, spilling over their faces, their open mouths, their hands fighting to catch it, to share it, to rub it into their skin. Jade takes the last pulse directly, her researcher nature making her thorough, complete, holding him in her throat until she's sure she's captured everything.
Then she sits back on her heels, her blouse open, her skirt ruined, her hair wild, and she looks for the pen.
She finds it. Writes the time in the margin of the file. Nothing else—no letter, no note, no analysis. Just the time. The last piece of the girl who sat in the second row on the first day of term, reduced to a reflex with nothing behind it.
<<else>>
Mia's lecture starts in twelve minutes and the room is full. Forty people, laptops out, someone in the third row asking whether the mid-term covers week four. The air is so thick with pheromones it leaves a film on the skin, a sweetness in the back of the throat that nobody questions anymore. The back rows have become a greenhouse of corruption, and the front—where the lecturer stands—has become the altar.
Jade is bent over the lecturer's desk, her blouse completely open, her skirt around her waist like a belt, her bare ass presented to the room. The file is beside her, open, because she still brings it, still opens it, still pretends. There is nothing usable in it anymore. The two columns stopped weeks ago. What's on the current page is her handwriting getting progressively worse down the sheet—because three times, the pattern is with nothing after, a line of times with no letters. She fills a page most days. She could not tell you what for.
<<speech "Jade">>(mumbling into the desk, her debater's mind reduced to loops) "Four more. You do four more and then you finish, that's the pattern, I've—"<</speech>>
<<speech "$name">>"You've charted it. You worked out my pattern before you worked out your own."<</speech>>
<<speech "Jade">>"I've //charted// it, it's in the— I've got it in the—"<</speech>>
She loses the number at three, as she does every time. That's what's left of the girl who could hold a five-point argument: she can still feel the shape of a sequence, she just cannot get to the end of one. She simply starts again, her hips pushing back against him, her researcher nature reduced to begging for the next data point.
<<speech "$name">>"What comes after three, Jade?"<</speech>>
<<speech "Jade">>"I don't— I can't— //Please//—"<</speech>>
Rae is naked on the desk beside her, waiting, her rebellious body marked with dark veining, her sharp tongue silenced into patience. She waits now. She, who never queued for anything, who took what she wanted, who planted ideas and watched them grow—she waits her turn.
<<speech "Rae">>"Her first."<</speech>>
<<speech "$name">>"You've never queued for anything in your life."<</speech>>
<<speech "Rae">>"She fought it for three months. I gave in the first week."<</speech>> She shrugs, entirely herself even in total submission. <<speech "Rae">>"Seems fair she goes first. That's all."<</speech>>
Caprice is in the aisle, her sketchbook open, but she's not drawing. She's watching, her artist's mind too far gone to create, only to observe, to witness, to confirm the reference. Her dress is gone, her cardigan tied around her waist, her pale body covered in dark tracery, her hand between her legs, pumping slowly.
<<speech "Caprice">>(her dry humor a whisper) "Do her properly. She's been holding that folder in front of herself since half nine and pretending it's about the module."<</speech>>
<<speech "Jade">>"It //is// about the—"<</speech>>
<<speech "Caprice">>"Jade. You've written the word 'because' three times and nothing after it."<</speech>>
<<speech "$name">>"Is that today's page or yesterday's?"<</speech>>
<<speech "Caprice">>"They're the same page. She just keeps starting it."<</speech>>
You breed Jade over the desk Mia will stand at in twelve minutes. She sobs through most of it, both hands flat on the wood either side of the open file, her researcher nature reduced to pure physical response. She comes twice before you finish, her walls convulsing, her arguments silenced into gasping, looping repetitions of "yes" and "please" and "more."
When you flood her, filling her womb, marking her as your breeding vessel, she collapses forward, her cheek on the page, her hips still tilted up, holding it in. She reaches out blindly, finds the pen, writes the time.
Nothing else. Just the time. The last reflex of the organized girl who sat in the second row, annotating her readings, dismantling weak arguments, knowing how many seats were in every room.
Then Rae takes her place, bent over the desk, her rebellious nature transformed to pure submission, her sharp tongue begging for the same treatment, the same filling, the same claim. She doesn't wait patiently anymore—she pushes back, demanding, her restlessness finally channeled into desperate need to be bred.
<<speech "Rae">>"Now me. Please. I've been good. I've been waiting. I've been—"<</speech>>
You take her, and she screams into the desk, her detention-hardened facade shattered, her body convulsing around you, milking you for everything Jade left.
Caprice last, her artist's body presented on the desk, her sketchbook finally used—not for drawing, but to prop her hips at the right angle, the pages beneath her soaking up the evidence of her arousal, her dry humor reduced to whispered thanks.
<<speech "Caprice">>"I've drawn this. I've drawn this a thousand times. Now I get to feel it. Now I get to be it."<</speech>>
You breed her, filling her, completing the set. The three of them—researcher, rebel, artist—reduced to breeding stock on the lecturer's desk, the file open beside them, the lecture due to start in minutes, forty students in the room who have adjusted, who no longer turn around, who simply wait for the knowledge to fill them the way the parasite fills their classmates.
Out in the class, someone asks about the mid-term. The lecturer will arrive eight minutes late. Jade will try to write that down. She will fail. She will start again.
<</if>>
<<case "Veruca_Class_Support">>
<<if _tier is 0 or _tier is 1>>
Last period, Thursday, and the room is at that stage of the afternoon where nobody has anything left. Twenty-odd desks, most of them full, the low continuous hum of a class that has decided the lesson is over with eleven minutes still on the clock.
Miss Veruca is new this year. You can tell from the whiteboard — she still writes the date in the corner, still underlines the objective, still turns her back on a room of eighteen-year-olds to do it. The older staff stopped doing all three years ago.
She's small and very put-together in a way the rest of the department isn't. Long black hair down her back in loose waves, dark eye makeup done with real care, red lipstick that has survived six hours of teaching. She looks like she dressed for a job she hasn't quite been given yet, and the effect is less authority than armour.
The back row under the window is the good row. The radiator runs along that wall and this building has two temperatures — arctic and this.
<<speech "Kailey">>"Budge."<</speech>>
<<speech "$name">>"There's a whole row."<</speech>>
<<speech "Kailey">>"There's a whole row and one radiator."<</speech>>
She drops into the seat beside you without waiting for the argument to resolve, bag hitting the floor, that wide open smile going the second she lands. Light brown hair with blonde running through it, pushed back off her face; she's been outside at lunch and brought the cold in on her jumper.
Vina is on your other side and has been all term. Dark wavy hair to her shoulders, that easy unbothered half-smile she wears at rest, sleeves pulled over her hands. You were close years ago and then simply weren't, and when the timetable put her at this desk in September she picked the conversation back up like there hadn't been a three-year gap, and never once made it awkward.
<<speech "Vina">>"Did you do the sheet?"<</speech>>
<<speech "$name">>"Half of it."<</speech>>
<<speech "Vina">>"Which half?"<</speech>>
<<speech "$name">>"The half that was on the front."<</speech>>
<<speech "Vina">>"So you didn't turn it over."<</speech>>
<<speech "$name">>"I did not turn it over."<</speech>>
She slides hers across without commentary, which is the entire reason people like Vina. At the front, Veruca is crouched by a desk in the second row talking somebody through a question — low, patient, one hand flat on the desk beside their paper. She's been at it four minutes. Two other hands are up and she hasn't seen them.
Riley is at the end of the back row against the wall, where she has sat every lesson since September. Light brown hair, straight, green eyes on her own page. In four months she has said perhaps nine sentences in this room and none longer than a phrase. She isn't sullen — she's self-contained in a way that reads, from a distance, as absence.
<<speech "Kailey">>"She's going to run over again."<</speech>>
<<speech "$name">>"She always runs over."<</speech>>
<<speech "Kailey">>"It's because she actually helps. Halloway says 'it's in the booklet' and does the crossword."<</speech>>
<<speech "Vina">>"To be fair, it usually //is// in the booklet."<</speech>>
<<speech "Kailey">>"Not the point, Vina."<</speech>>
The bell goes and half the room is standing before it stops. Veruca straightens up too fast, says something apologetic about next week that nobody hears, and starts gathering paper she's already gathered once.
You're most of the way to the door when Riley speaks, and it takes a second to register that it's aimed at you.
<<speech "Riley">>"You got six wrong the same way I did."<</speech>>
You stop. So does Kailey, with visible interest.
<<speech "$name">>"Was it right, or were we both wrong in the same direction?"<</speech>>
<<speech "Riley">>"Wrong. But wrong in an interesting way, because the method's fine, it's the second step where you both— hang on—"<</speech>>
She has her book open on somebody else's desk and is drawing on it upside down. Nine minutes later Miss Veruca is standing by the light switch waiting to lock up and being far too polite to say so, and Riley is still going.
<<speech "Kailey">>"…I've never heard her talk."<</speech>>
<<speech "Vina">>"Nobody has."<</speech>>
<<speech "Riley">>"I can hear you. I literally talk with you two everyday."<</speech>>
<<elseif _tier is 2>>
The back row has consolidated. Nobody suggested it. The three of them are packed into the two desks nearest the radiator with you in the middle, and the rest of the row sits empty like something spilled outward.
Riley hasn't stopped talking since the last week of October.
<<speech "Riley">>"—which is what I said, but he wouldn't have it, because his whole thing is if you can't show the working it doesn't count, and I said fine, but then what's the //point// of being able to do it in your head—"<</speech>>
<<speech "$name">>"Riley."<</speech>>
<<speech "Riley">>"Mm?"<</speech>>
<<speech "$name">>"That was Tuesday. You told me this on Tuesday, in the corridor, for about the length of the corridor."<</speech>>
<<speech "Riley">>"Did I get to the bit about the marking scheme?"<</speech>>
<<speech "$name">>"You got to the bit about the marking scheme."<</speech>>
<<speech "Riley">>"Right. Well. There's more of it."<</speech>>
The lock came open and there's no closing it. She's moved down the row a desk a week, slow enough that nobody can point at the day, and she now sits with her chair turned in towards yours and her forearm along the edge of your desk. Green eyes on your face the whole time she talks. She has stopped bringing anything to write with.
The school jumper is off and over the back of the chair. Blouse untucked, top two buttons undone and the third going the same way as the afternoon warms up, and when she leans in to make a point — which is constantly — the gap falls open and there's plainly nothing under it. Her knee has been resting against yours for forty minutes.
Vina has her chair tipped back on two legs, cardigan slipping off one shoulder, entirely unbothered. She reaches over and takes your pen without asking, uses it, and puts it back — a thing she's done forty times this term and which neither of you has ever remarked on. Under the desk her foot is out of her shoe and the arch of it is running slowly up and down your calf, and she is looking straight ahead at the whiteboard while she does it.
<<speech "Vina">>"She's talking about Halloway again."<</speech>>
<<speech "Riley">>"I'm //aware// of what I'm talking about."<</speech>>
<<speech "Vina">>"I'm saying it out loud so you can hear how long it's been."<</speech>>
<<speech "$name">>"Both of you are very warm today."<</speech>>
<<speech "Vina">>"It's the radiator."<</speech>>
The radiator has been off since the boiler failed on Monday. Nobody corrects her. Nobody notices.
Kailey has her chair pulled round so she's half-facing you and has been quiet most of the lesson, which for Kailey is close to alarming. She keeps starting to say something and putting it away. When she finally leans in it's close enough that her hair brushes your jaw.
<<speech "Kailey">>"Can I say a thing and you not turn it into a joke."<</speech>>
<<speech "$name">>"That depends entirely on what it is. Say it and find out."<</speech>>
<<speech "Kailey">>"Everyone's been odd since about half term. Not bad-odd. Just—"<</speech>>
She stops, and her hand arrives high on your thigh under the desk in a way that has clearly been queued for some time. It doesn't stay still. Her palm slides up the inside seam of your trousers until her fingertips are unmistakeably against you, and she keeps her eyes on the front of the room the entire time and her voice completely level.
<<speech "Kailey">>"—and I'm doing it as well. That's the bit I keep getting stuck on. I'm doing it as well and I don't mind."<</speech>>
<<elseif _tier is 3>>
This class was almost empty today. Twenty desks, four people, and an extractor fan that's the loudest thing in the building.
Miss Veruca locks the door now. She does it on the way in without breaking whatever sentence she's in, and hangs her lanyard over the handle so the little window is covered.
<<speech "Veruca">>"Right. Carry on with what you were doing."<</speech>>
Nobody is doing anything.
Riley is under the desk before you're properly into the chair. She gets to the room first specifically so she can be there when you arrive and she has never once acknowledged this out loud. She has your belt open and your cock out and in her mouth within about fifteen seconds, and she is still talking in the gaps.
<<speech "Riley">>"—couldn't concentrate in fourth period, just sat there, and I've decided that's your fault—"<</speech>>
<<speech "$name">>"Riley."<</speech>>
<<speech "Riley">>"—mm?"<</speech>>
<<speech "$name">>"You've had six weeks of talking. Do the other thing instead."<</speech>>
She stops for nearly four minutes, which from Riley is a devotional act. What she does instead is take you all the way down until her nose is against your stomach and hold there, throat working, green eyes watering and fixed up at your face, and then come off gasping and go straight back down.
Vina has her skirt pushed up and one bare foot on the chair rail, two fingers working unhurriedly inside herself, sleeves still over her other hand. There's no urgency in her at all. There was never any resistance to strip out of Vina — she agreed to this the way she agrees to everything, with a small shrug and a shift in the seat, and slid into it like a routine she'd been on before. Her chair is wet under her and she hasn't mentioned it.
<<speech "Vina">>"You'll finish in her and then it's me. Yeah?"<</speech>>
<<speech "$name">>"Yeah. And you'll wait for it without making a thing of it, same as always."<</speech>>
<<speech "Vina">>"Obviously."<</speech>>
<<speech "Kailey">>"How is she //like// this—"<</speech>>
Kailey is not like this. Kailey is mostly in your lap with her blouse open and her bra shoved up under her arms, grinding down against your thigh through her skirt while she kisses your throat, and she has gone from //I don't want to push// to being physically unable to hold still.
<<speech "Kailey">>"Sorry. Sorry, I know, I'm being— I've tried to be normal about this all week—"<</speech>>
<<speech "$name">>"Stop trying. Nobody in this room wants the normal version of you."<</speech>>
<<speech "Kailey">>"…That works every single time. Say it again in a minute."<</speech>>
She takes over from Riley halfway through without discussing it, and Riley doesn't fight her for it — the two of them end up shoulder to shoulder under the desk with their mouths working either side of you, Kailey messy and enthusiastic and Riley precise, and every so often they lose track of whose turn it is and kiss each other with you in between.
<<else>>
There is no support class. There's a locked room on the top corridor with twenty desks pushed against three walls and one desk left in the middle, and the timetable still says the lesson happens, and in a sense it does.
The radiator has been on all winter. The air in here is hot and wet and sweet and the inside of the window runs with it.
They're already in position when you come in, because they're always already in position; the three of them arrive at lunch now and simply stay.
Riley is on her knees by the middle desk in a blouse and tie and nothing else, light brown hair stuck to her forehead, thighs wet to the knee. The flood of talk is gone — the whole two-year lock and everything that came out of it — and what's left is one short loop she runs at speed while she waits.
<<speech "Riley">>"First. I'm first. I got here at twelve, tell me I'm first—"<</speech>>
<<speech "$name">>"You're first, Riley. You're first every day."<</speech>>
<<speech "Riley">>"//Every day.//"<</speech>>
Vina is face-down over the middle desk with her skirt rolled to her waist and nothing under it, ankles crossed, cheek on the wood, dark hair spread over somebody's old graffiti. Veining runs up the backs of her thighs. She's been waiting like that a while and would wait considerably longer without complaint. There's a wet ring on the desk where she's been resting against it.
<<speech "Vina">>"Whenever."<</speech>>
<<speech "Kailey">>"//Whenever//, she says. Every time."<</speech>>
<<speech "Vina">>"He'll get to me."<</speech>>
Kailey can't do that and has stopped pretending to. Whatever the parasite took, it left the part that watches — she knows who went last, who got missed, whose week it is — and she runs the room on it with a clipboard she took from the front desk and never gave back.
<<speech "Kailey">>"Vina's mid-cycle. She goes second, not third."<</speech>>
<<speech "Riley">>"I'm still first."<</speech>>
<<speech "Kailey">>"Nobody's touching your slot, Riley, God."<</speech>>
<<speech "$name">>"And where do you put yourself in all this, Kailey?"<</speech>>
<<speech "Kailey">>"Last. I like watching it work."<</speech>> The composure lasts two seconds. <<speech "Kailey">>"That's a lie. I've been in this room since half twelve thinking about it and I mind //enormously//, please don't make me go last again—"<</speech>>
<<speech "$name">>"Then you're second and Vina's third."<</speech>>
<<speech "Vina">>"Fine by me."<</speech>>
You take Riley over the middle desk first because Riley has earned first, and she goes off within a minute with her fingernails dragging four pale lines down the varnish. She keeps up the loop the whole way through, //first, I'm first, I'm always first//, until it stops being words.
Kailey second, on her back on the desk with the clipboard still in one hand — she genuinely will not put it down — and she comes twice and forgets which day it is, and afterwards has to ask Vina who's left.
Vina third, exactly where she has been waiting the whole time, unbothered to the last. She takes it with her cheek on the wood and her fingers hooked over the far edge of the desk and she says //thanks// afterwards, in the same tone she'd use for a lift home.
<</if>>
<<case "Chanel_Class_Standard">>
<<if _tier is 0 or _tier is 1>>
Professor Chanel has rearranged the seating chart again.
She does this roughly once a month, always without explanation, and the class has learned not to argue. The new arrangement has put Violet in the front row and Vanna three seats back and one column over — which, to anyone paying attention, is a deliberate act of separation.
Violet is not taking it well.
<<speech "Violet">>"This is //targeted//."<</speech>>
<<speech "Chanel">>"It's alphabetical."<</speech>>
<<speech "Violet">>"It is //not// alphabetical, I sat next to Alex last month and her name starts with—"<</speech>>
<<speech "Chanel">>"It's alphabetical by a system I find useful. Sit down, Violet."<</speech>>
<<speech "$name">>"It's not alphabetical."<</speech>>
<<speech "Chanel">>"Thank you, $name."<</speech>>
<<speech "$name">>"I'm agreeing with her."<</speech>>
<<speech "Chanel">>"I know. Sit down as well."<</speech>>
Violet sits down. She does it with enormous theatrical injury, dropping into the chair like a woman collapsing at the end of a long war, and immediately turns around to make eye contact with you at the back.
Behind her, Vanna is examining her nails with the studied indifference of someone who has absolutely noticed that Violet got the front row and is absolutely not going to mention it.
<<speech "Vanna">>"Some of us don't need to be managed."<</speech>>
<<speech "Violet">>"Some of us aren't //interesting// enough to manage."<</speech>>
<<speech "$name">>"She put you eleven feet apart, Vanna. That's management."<</speech>>
<<speech "Vanna">>"…That's a good point actually."<</speech>>
<<speech "Chanel">>"All three of you. Enough."<</speech>>
She says it without raising her voice, and all three of you stop instantly, which is the thing about Chanel — the room adjusts around her without her ever appearing to ask.
The lecture is on group behaviour, which she delivers with the dry pleasure of someone describing an experiment she is currently running. Violet takes no notes and watches you instead. Vanna takes excellent notes and pretends she isn't watching Violet not take notes.
When the bell goes, Chanel says your name.
<<speech "Chanel">>"A moment."<</speech>>
Violet's head snaps around. Vanna packs her bag very slowly.
Chanel waits until they're both out of the door, then leans back against her desk and studies you with the same expression she uses on a difficult text.
<<speech "Chanel">>"You've been tired lately."<</speech>>
It isn't a question, and she doesn't leave a gap for one.
<<speech "$name">>"Is that on the seating chart too? Tired at the back, awake at the front?"<</speech>>
<<speech "Chanel">>"Everything's on the seating chart."<</speech>>
<<speech "$name">>"I've been up late. That's all it is. There's a lot on at the moment and I'm handling it."<</speech>>
<<speech "Chanel">>"Mm."<</speech>> She turns back to her papers. <<speech "Chanel">>"I don't need an answer, $name. I'd just like you to know I noticed. Go on — Violet's waiting in the corridor pretending to look at the noticeboard."<</speech>>
Violet is waiting in the corridor pretending to look at the noticeboard.
<<elseif _tier is 2>>
The seating chart has stopped being enforced.
Nobody announced it. Chanel simply stopped correcting people, and within a week Violet had relocated to the desk beside yours and Vanna had taken the one directly behind — close enough that when she leans forward to ask a question, her chest presses against your shoulder blade and stays there.
<<speech "Vanna">>"Sorry. Cramped in here."<</speech>>
It is not cramped in here. There are eleven empty desks.
Violet has given up on any pretence of subtlety. Her chair is angled toward you, her skirt is shorter than the dress code technically permits, and her hand has been resting high on your thigh since the lecture began, thumb tracing slow circles through the fabric.
<<speech "Violet">>"You're not listening to a word she's saying."<</speech>>
<<speech "$name">>"Neither are you."<</speech>>
<<speech "Violet">>"I //never// listen. You usually do. That's the difference and I'm very pleased about it."<</speech>>
She leans in and kisses you — properly, unhurried, in the third row of an occupied classroom — then settles back into her chair looking enormously satisfied with herself.
Behind you, Vanna makes a small noise.
<<speech "Vanna">>"You're both disgusting."<</speech>>
<<speech "Violet">>"You're welcome to leave."<</speech>>
Vanna does not leave. Vanna leans further forward, close enough that her breath moves the hair at the back of your neck, and slides one hand over your shoulder and down your chest.
<<speech "Vanna">>"I just think if you're going to do it, you could do it with someone who isn't going to cry about it later."<</speech>>
<<speech "Violet">>"I have //never//—"<</speech>>
<<speech "Vanna">>"You cried at a film about a dog."<</speech>>
<<speech "$name">>"Vanna, come round the front."<</speech>>
There is a pause of about a second in which the version of you from last term would have turned the sentence into a joke.
<<speech "Vanna">>"…What?"<</speech>>
<<speech "$name">>"You've been leaning over my shoulder for forty minutes so that I'd notice you and not say anything about it. I've noticed. Come round the front where I can see you properly."<</speech>>
<<speech "Violet">>"He's //mine// this period—"<</speech>>
<<speech "$name">>"There's no period. There's a room with eleven empty desks in it and both of you are in the one I'm sitting at."<</speech>>
Vanna comes round the front. She sits on the edge of your desk with her back to the board, knees apart, and looks anywhere but at you, red to the collarbone and entirely unwilling to be the first one to move.
At the front, Chanel has stopped mid-sentence.
She's looking at the three of you over the top of her glasses with an expression you can't quite read — not scandal, not anger. Something closer to a researcher noticing that her sample has begun doing something she didn't design for.
<<speech "Chanel">>"…adolescent competition. Which, as it happens, is our topic."<</speech>>
She turns back to the board and keeps talking. Her voice stays level. Her collar is undone one button further than it was at the start of term, there's a flush along her throat that has nothing to do with the temperature, and her free hand — the one not holding the marker — has disappeared into the folds of her skirt and is quite clearly, quite rhythmically busy.
She does not stop lecturing. She does not stop the other thing either.
Violet's hand slides higher. Vanna's fingers curl into your collar. Neither of them so much as glances at the front of the room.
<<elseif _tier is 3>>
The door is shut. Chanel shuts it herself now, without breaking stride, the way you'd close a door on a private conversation.
<<speech "Chanel">>"We'll continue from Thursday."<</speech>>
Nobody continues from Thursday.
Violet is on her knees between your feet before you've finished sitting down, and the theatre is gone — that's the change. No announcement, no performance. She just wants her mouth on you and she's stopped constructing a reason.
<<speech "Violet">>"I waited all day. All //day//, and you were in Amber's class doing nothing, and I sat here."<</speech>>
<<speech "$name">>"Then stop talking about it."<</speech>>
<<speech "Violet">>"//Yes.//"<</speech>>
Vanna has pulled a desk over and is sitting on it beside you, skirt gone, legs open, working herself with two fingers while she watches Violet work. The superiority has burned off. What's underneath is the part it was covering.
<<speech "Vanna">>"Look at me too."<</speech>> It comes out smaller than she meant it to. <<speech "Vanna">>"I don't— just look at me too, that's all."<</speech>>
<<speech "$name">>"Vanna. I've been looking at you since you sat on that desk, and you knew that, and you asked anyway."<</speech>>
<<speech "Vanna">>"…So?"<</speech>>
<<speech "$name">>"So stop asking to be included and get down here and use your mouth."<</speech>>
She's off the desk instantly. She shoulders in beside Violet without apologising, and the two of them work you together — Violet greedy and messy, Vanna precise and competitive, neither willing to be the one who gives ground.
At the front, Professor Chanel leans back against her own desk with her skirt pushed up and one hand between her thighs, watching with an expression of terrible academic focus. Her glasses are still on. Her voice is perfectly level.
<<speech "Chanel">>"Violet. You're rushing. He responds better when you slow down — you've had six weeks to learn that."<</speech>>
<<speech "Violet">>"I'm not taking notes from you on //this//—"<</speech>>
<<speech "$name">>"Do what she says, Violet."<</speech>>
Violet slows down. Chanel makes a small satisfied sound and doesn't stop what her own hand is doing.
<<speech "Chanel">>"Better. Vanna, share it — don't hoard. You always hoard."<</speech>>
<<speech "Vanna">>"I'm not //hoarding//—"<</speech>>
<<speech "$name">>"Chanel. Down here."<</speech>>
The professor crosses her own classroom, kneels on the floor she used to lecture from, and joins them without a word of protest, and when you finish it is across all three of their faces at once. Vanna turns to Violet to say something cutting and Chanel simply guides the two of them together by the backs of their heads until they're sharing it between their mouths.
<<speech "Chanel">>"There. Now nobody went first."<</speech>>
<<else>>
The classroom isn't a classroom. The desks are shoved against the walls, the blinds are down, and the air is so thick with the parasite's scent that it condenses on the windows and runs down in slow lines.
Professor Chanel is on her knees on the floor she used to lecture from, naked but for her glasses, the parasite's dark tracery climbing her ribs and throat. The brilliant mind is still in there — that's what makes it obscene. She is still analysing. She has simply reduced the scope of her analysis to one subject.
<<speech "Chanel">>"Come here. I've been thinking about the optimal—"<</speech>> Her breath catches as you approach. <<speech "Chanel">>"—about how best to take you. I've been thinking about it for eleven hours. I couldn't stop. I missed a faculty meeting."<</speech>>
<<speech "$name">>"Eleven hours. Tell me the result."<</speech>>
<<speech "Chanel">>"Violet first, she's loudest and she settles the room. Vanna second, she needs to be chosen and she'll sulk all week if she isn't. Me last and twice, because I'm the only one here who can still hold a thought, and I would very much like to stop."<</speech>>
<<speech "$name">>"Then stop. You've done the work. You don't have to be the clever one in here any more."<</speech>>
<<speech "Chanel">>"…//Oh.//"<</speech>>
<<speech "Chanel">>"//Thank you.//"<</speech>>
Violet is spread on the front desk, ankles hooked over the edge, cunt swollen and leaking down onto the wood where Chanel used to set her lecture notes. She is beyond drama now. She is beyond most things.
<<speech "Violet">>"Me first. Me first, please, I'm the one who— I've always been the one who—"<</speech>>
<<speech "Vanna">>"Shut //up//, Violet."<</speech>>
Vanna is behind her with one hand around Violet's throat and the other buried between her legs, working her roughly. Whatever competition existed between them has resolved into this: a hierarchy they settled without you.
<<speech "Vanna">>"She goes first because she begs prettiest. I go second because I last longer."<</speech>> She looks up, and there is nothing insecure left in her face at all. <<speech "Vanna">>"Professor goes whenever you want her. She said so."<</speech>>
<<speech "Chanel">>"It's the only fair distribution. I ran it through several models."<</speech>>
You take Violet on the desk. She goes off before you're fully in her and keeps going, hands scrabbling at the edge of the wood, and Vanna holds her open with two fingers and watches where it goes with her mouth hanging open.
<<speech "$name">>"Deeper or harder, Violet. You get one. Pick."<</speech>>
<<speech "Violet">>"//Both// — both, please, I don't— I can't pick, don't make me pick anything ever again—"<</speech>>
You breed her over the desk and she sobs through the whole of it, and Vanna is already climbing up beside her before you've finished, spreading herself out on the same wood, begging to be chosen out loud for the first time in her life.
<<speech "Vanna">>"Say my name first. Just once. Say it before you do it—"<</speech>>
<<speech "$name">>"Vanna. I'm choosing you. I'm choosing you in front of both of them."<</speech>>
<<speech "Vanna">>"//Again.//"<</speech>>
<<speech "$name">>"Vanna."<</speech>>
Chanel kneels between your feet the entire time with her mouth on your thigh and her hand between her own legs, waiting her turn with the patience of a woman who has calculated exactly how long it will be, murmuring corrections to your angle that you follow because they are, invariably, correct.
The bell rings somewhere in the building. Nobody in this room has any idea what it means any more.
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<set $sceneColor = "#ffcc44">>
<<set $sceneLabel = "Academic · Campus">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "Library_Standard">>
<<if _tier is 0 or _tier is 1>>
The school library runs on the assumption that everybody in it wants to be left alone, which is Shazia's doing. She is the librarian — soft-spoken, dark-haired, permanently half-hidden behind the returns desk or between the shelves — and she avoids confrontation so completely that the room has quietly organised itself around never requiring any.
$name is here because there are four boxes of stock that came in on a trolley and nobody who works here can lift them.
<<speech "Shazia">>"You don't have to do all of them. Two would be a kindness."<</speech>>
<<speech "$name">>"If I do two, you'll do the other two after I've gone and hurt your back."<</speech>>
<<speech "Shazia">>(after a small pause) "…That is what I was going to do, yes."<</speech>>
Caprice is on the fiction aisle with a cart, shelving. She works here part-time and helps Shazia keep the place upright, and she has the flat delivery of somebody whose jokes get mistaken for coldness about half the time.
<<speech "Caprice">>"Don't let her guilt you. She's been moving those boxes six at a time all week using willpower and denial."<</speech>>
<<speech "Shazia">>"That isn't true."<</speech>>
<<speech "Caprice">>"You did it on Monday. I watched you do it and said nothing because I'm a coward."<</speech>>
<<speech "$name">>"Then I'll do all four and neither of you has to be brave about it."<</speech>>
Natalie is at the corner table she has occupied for most of the term, blonde, septum piercing, laptop and three open books and a spread of printouts. She is deep in a thesis and has no interest in anybody's business, which in a school is close to a superpower.
<<speech "$name">>"How's the data? You said it was fighting you last week."<</speech>>
<<speech "Natalie">>"Wrong. Consistently wrong, in the same direction, which means it's either a real finding or I've made an error in the setup."<</speech>>
<<speech "$name">>"So which is it — a finding, or a term of your life gone?"<</speech>>
<<speech "Natalie">>"Ask me on Thursday. Thursday is when I find out whether I've wasted a term."<</speech>>
She doesn't look up while she says any of it. Caprice slots three books in without checking the numbers and gets all three right.
The boxes get moved. Shazia thanks him twice, which is once more than necessary and about a tenth of what she's thinking, and the room settles back into its arrangement of people not bothering each other.
<<elseif _tier is 2>>
The library is quiet in the way it always is. Somebody is asleep at the far table. The photocopier makes its noise. The air has thickened, sweet and close, and nobody has said anything about that, because nobody in this room says anything about anything.
Shazia is at the returns desk working through a stack. Her cardigan has slipped off one shoulder and stayed there. She is stamping and sorting at the same steady rate she always does, and when $name comes round behind the desk and puts a hand inside the cardigan she leans back into him and keeps stamping.
<<speech "Shazia">>"These are all overdue. Nobody's paid a fine in this school in four years."<</speech>>
<<speech "$name">>"Do you ever chase them? Any of them, ever?"<</speech>>
<<speech "Shazia">>"I send a note. Then I don't send a second note, because a second note is a confrontation."<</speech>>
Her breath is uneven under his hand and her voice is not. A student comes to the desk with a book. Shazia takes it, stamps it, hands it back, says thank you, and does not shift away from him for any of it. The student leaves without looking up from her phone.
Caprice is on the ladder in the aisle. Her skirt is doing very little from below and she has made no adjustment. When $name puts a hand up the back of her thigh she shifts her weight to the other foot to give him room and carries on shelving.
<<speech "Caprice">>"Someone's put the whole of the R's in backwards. Spine-in. Every one."<</speech>>
<<speech "$name">>"Somebody did that on purpose. Every single one, spine-in."<</speech>>
<<speech "Caprice">>"That is somebody making a statement and I do not have the energy to work out what it was."<</speech>>
She pulls them out one at a time and turns them and puts them back, and her thighs are pressed together, and she does not stop.
Natalie is at the corner table and has not moved in an hour. Her shirt is undone lower than it starts a day. She types with one hand for a while and then with none, and her free hand has gone under the table, and her eyes stay on the screen the entire time.
<<speech "Natalie">>"The Thursday thing might be a real finding. I ran it again."<</speech>>
<<speech "$name">>"You told me Thursday. Twice, quite firmly."<</speech>>
<<speech "Natalie">>"I couldn't wait. I'm not good at waiting for things, it turns out."<</speech>>
Her hand stops. Her whole body locks — a sharp breath in, knuckles white on the edge of the table, eyes still open on the screen — and for a few seconds she is gone entirely. Then it passes and she blinks and scrolls back up the page.
<<speech "Natalie">>"…Where was I."<</speech>>
<<speech "$name">>"You'd run it again. Because you couldn't wait until Thursday."<</speech>>
<<speech "Natalie">>"Right. So I did."<</speech>>
The photocopier finishes. The person at the far table sleeps on.
<<elseif _tier is 3>>
The library does not close until six and it is not six. The doors are open and the lights are on and the sign on the desk still says the desk is staffed.
Shazia comes out from behind it and kneels on the floor between the returns trolley and the wall, which is the least visible spot in the room and the closest thing to a decision she has made all term.
<<speech "Shazia">>"Here is fine. Nobody comes round this side."<</speech>>
<<speech "$name">>"Somebody is going to come to that desk in a minute."<</speech>>
<<speech "Shazia">>"Then they'll wait. People are very good at waiting at a desk."<</speech>>
She takes him quietly, which is how she does everything, and does not stop when the front door goes and somebody walks in and along the far aisle and out again.
Caprice comes down the ladder and joins her without being asked, dropping onto her knees with the flat efficiency of somebody putting a box down.
<<speech "Caprice">>"Move your elbow."<</speech>>
<<speech "Shazia">>"Sorry."<</speech>>
<<speech "$name">>"Neither of you is going to acknowledge this at all, are you."<</speech>>
<<speech "Caprice">>"I acknowledged your elbow. That's as far as I go before six."<</speech>>
<<speech "$name">>"Somebody just walked the length of the far aisle and out again."<</speech>>
Natalie arrives last and brings a printout with her, which she sets face down on the trolley before she kneels, so it doesn't get wet.
<<speech "Natalie">>"Two minutes. I've got a chapter open."<</speech>>
<<speech "$name">>"You've said two minutes about everything for an entire term."<</speech>>
<<speech "Natalie">>"And it has always been true."<</speech>>
The three of them take him in turns on the floor of a working library, and nobody hurries, and nobody says anything about it, and the returns stack sits on the desk unattended with a queue of nobody in front of it.
<<else>>
The library is open. It says so on the door. Shazia still stamps the returns each morning and puts the trolley out.
She is over the returns desk with her skirt gone, the overdue stack still under her forearms. Caprice is sitting on the edge of the fiction shelf with her legs open, waiting, in no hurry. Natalie is on the floor by the corner table with the laptop still running above her.
<<speech "Shazia">>"Whenever. I've got until six."<</speech>>
<<speech "$name">>"And after six? You've thought about after six."<</speech>>
<<speech "Shazia">>"After six I lock the door and we do it again without the interruptions."<</speech>>
You take her over the desk and she braces on her forearms and moans low into the paperwork, quietly, because it is a library and some part of her is still tracking that.
<<speech "Shazia">>"That's — yes — fill me, I want to sit at this desk full of it —"<</speech>>
Caprice waits her turn and takes it bent over the same desk, and she is dry about it right up until she isn't.
<<speech "Caprice">>"Deeper. That's not a joke, I've stopped making jokes about this."<</speech>>
<<speech "$name">>"You have never once stopped making jokes. Not in all the time I've known you."<</speech>>
<<speech "Caprice">>"I've stopped. Breed me and I'll start again afterwards."<</speech>>
<<speech "$name">>"Hold on to the desk, then, and stop talking about it."<</speech>>
Natalie last, on her back on the floor with her heels up on the table edge, and she talks through the whole of it because the thesis is still there.
<<speech "Natalie">>"It was a real finding, by the way. Thursday. It held."<</speech>>
<<speech "$name">>"You are telling me about your data. Right now, while I'm inside you."<</speech>>
<<speech "Natalie">>"I'm telling you it held. Now put it in me and I'll write it up in the morning."<</speech>>
Afterwards the three of them stay where they are, leaking onto the desk and the carpet, unhurried. Somebody comes to the front desk, waits a while, gives up, and leaves the book in the returns slot.
<</if>>
<<case "Library_Study">>
<<if _tier is 0 or _tier is 1>>
Adria has booked the long table by the east window and laid the study session out like a military operation — printed schedules, a shared document open on three laptops, and a stack of index cards nobody is going to touch.
<<speech "Adria">>"Ninety minutes. Three blocks of twenty-five, five-minute breaks, then a review. I've done the timings."<</speech>>
<<speech "$name">>"You've done the timings."<</speech>>
<<speech "Adria">>"I've //done// the timings."<</speech>>
<<speech "Kyler">>"He said that in exactly the voice I was going to say it in."<</speech>>
<<speech "Adria">>"Then you can both leave."<</speech>>
<<speech "$name">>"You booked a table for four and there are four of us. You'd have to explain the empty chairs to yourself."<</speech>>
Adria points at you with her pen, finds no counter-argument, and lowers the pen.
Kyler drops into the chair beside you with the easy competence she does everything with — bag down, laptop open, pen uncapped, all in one motion.
<<speech "Kyler">>"Sorry I'm late. Megan had me on the quarterly deck until six and then she made me stay another ten minutes to tell me it was good."<</speech>>
<<speech "$name">>"That's a strange complaint."<</speech>>
<<speech "Kyler">>"It's not a complaint! It was good. I fixed the thing where all the graphs were different colours for no reason."<</speech>> She's genuinely pleased about it. <<speech "Kyler">>"Nobody had touched that template in four years."<</speech>>
<<speech "$name">>"So it was a good day."<</speech>>
<<speech "Kyler">>"It was a good day."<</speech>>
Professor Adriana is at the head of the table, marking. She installed herself here weeks ago on the grounds that the library is quieter than the staff room, which is untrue, and everyone knows it's untrue, and nobody says so, because she's cool.
She caps her pen.
<<speech "Adriana">>"And after the internship?"<</speech>>
<<speech "Kyler">>"…After?"<</speech>>
<<speech "Adriana">>"It ends in April. What then?"<</speech>>
<<speech "Kyler">>"I'll see what's going. Megan says she'll write me something."<</speech>>
<<speech "Adriana">>"That isn't what I asked."<</speech>>
<<speech "Kyler">>"I know."<</speech>> She says it lightly, without any edge at all, and goes back to her laptop. <<speech "Kyler">>"You ask me that about every six weeks."<</speech>>
<<speech "Adriana">>"And you give me the same answer."<</speech>>
<<speech "Kyler">>"It's a good answer. It's a //true// answer. Everyone keeps looking at me like there's a better one and there just isn't one yet."<</speech>>
<<speech "Adriana">>"There isn't supposed to be, at your age. The trouble is nobody tells you that, so you all spend three years assuming everyone else got a letter you didn't."<</speech>>
<<speech "Kyler">>"Adria got the letter."<</speech>>
<<speech "Adriana">>"Adria wrote her own letter and laminated it."<</speech>>
<<speech "Adria">>"I am //not//—"<</speech>>
<<speech "Adriana">>"Five-year plan. In your bag. Right now."<</speech>>
Adria opens her mouth, closes it, and looks at her schedule with tremendous intensity.
<<speech "Kyler">>"It's //laminated//?"<</speech>>
<<speech "Adria">>"It's in a plastic wallet, which is completely different—"<</speech>>
<<speech "$name">>"How different?"<</speech>>
<<speech "Adria">>"Structurally! It can be //updated//, that's the entire point of the wallet—"<</speech>>
<<speech "Adriana">>"And how many times have you updated it?"<</speech>>
A pause of exactly the wrong length.
<<speech "Adria">>"…Twice."<</speech>>
<<speech "Kyler">>"See, this is why I don't have one. Imagine being //disappointed// by a piece of paper."<</speech>>
<<speech "Adria">>"It's not disappointing, it's //aspirational//—"<</speech>>
Shazia drifts past the end of the table, shushes the four of you so quietly that it barely disturbs the air, and drifts away again. Adriana lifts her tea in salute without looking up.
The first twenty-five-minute block passes in genuine silence, and it's good work — you get two of Adria's problem sets out of the way and Kyler catches a mistake in yours before you commit it to the shared doc.
Somewhere around minute eighteen her shoulder settles against yours and stays there. You're fairly sure neither of you noticed it happening. Adriana notices, glances for perhaps a second and a half, and says nothing at all.
Something warm turns over low in your chest, once, like a sleeper changing position.
<<elseif _tier is 2>>
The schedule has degraded.
Adria still brings it. She still lays it out at the start. But the twenty-five-minute blocks have become suggestions, the five-minute breaks have become however long anyone feels like, and last week nobody opened a laptop at all.
Kyler has stopped pretending she came here to study. She's in the chair beside you turned fully sideways, one leg hooked over yours, cardigan on the floor, blouse open two buttons further than a heated building requires.
<<speech "Kyler">>"Can I tell you something? Work was good today. Genuinely good — Megan gave me the client call and I ran the whole second half."<</speech>>
<<speech "$name">>"That's not nothing."<</speech>>
<<speech "Kyler">>"It's not nothing. I was pleased for about four hours."<</speech>> Her hand is flat on your stomach under the table, sliding lower with no particular urgency. <<speech "Kyler">>"And then I got in the lift and I thought, //right, and now the good part,// and the good part was coming //here.//"<</speech>>
<<speech "$name">>"Say the rest of it."<</speech>>
<<speech "Kyler">>"There isn't a rest of it. That's what's strange."<</speech>> She frowns at her own hand like it belongs to somebody more decisive. <<speech "Kyler">>"I've never wanted a //specific// thing before. I've wanted things to go fine and they mostly have. This is the first time I've caught myself wanting one exact thing and it's a table in a library."<</speech>>
<<speech "$name">>"Then keep wanting it. You've spent years being fine with whatever turned up. You're allowed to want one exact thing."<</speech>>
<<speech "Kyler">>"…Oh."<</speech>> She laughs, a little unsteadily, and doesn't stop. <<speech "Kyler">>"Okay. You've got much worse at pretending too, you know."<</speech>>
<<speech "$name">>"I know."<</speech>>
<<speech "Kyler">>"I liked it better when we were both being polite about it."<</speech>>
<<speech "$name">>"No, you didn't."<</speech>>
<<speech "Kyler">>"No, I didn't."<</speech>>
She kisses you, unhurried, one hand still working under the table, and nobody at this table remarks on it.
Across the way Adria is failing, visibly, to run the session. Her pen has stopped. She's watching Kyler's wrist move and her own thighs are pressed tight together and she has read the same line of her notes four times.
<<speech "Adria">>"We're— the second block was supposed to start at—"<</speech>>
<<speech "Kyler">>"Mm-hm."<</speech>>
<<speech "Adria">>"—at ten past, and it's—"<</speech>>
<<speech "$name">>"Adria."<</speech>>
<<speech "Adria">>"//What.//"<</speech>>
<<speech "$name">>"Come sit over here."<</speech>>
She looks at the door. She looks at her schedule. She looks at the door again — and Professor Adriana, who has been listening to all of it, reaches over, slides the schedule out from under Adria's hands and turns it face-down on the table.
<<speech "Adriana">>"Go on, sweetheart. He asked you properly."<</speech>>
Adria comes and sits over here.
She lands close enough that her knee presses against yours, puts her hand on your arm and leaves it there like she's testing whether it's allowed. You cover her hand with yours. She makes a very small sound and looks straight ahead at nothing.
<<speech "Adria">>"This is a //study session//."<</speech>>
<<speech "$name">>"It is. You booked it."<</speech>>
<<speech "Adria">>"I did book it."<</speech>>
Adriana doesn't go back to her marking. She gets up instead, walks the length of the table with her tea and settles on the tabletop beside your chair — sitting on it, close enough that her stocking brushes your forearm.
<<speech "Adriana">>"Don't mind me."<</speech>>
<<speech "Adria">>"You're //supervising//."<</speech>>
<<speech "Adriana">>"I'm observing. There's a difference and I teach it."<</speech>> She looks down with unhurried, warm interest that a professor should not have. <<speech "Adriana">>"Although — Adria, you're gripping his arm like it's a railing. He isn't going anywhere. Loosen your hand and use it."<</speech>>
<<speech "Adria">>"…Use it."<</speech>>
<<speech "Adriana">>"Use it."<</speech>>
Adria's hand slides off your arm and into your lap. Adriana watches it go, and then — entirely unhurried, still holding her tea in the other hand — reaches under the hem of her own skirt and settles into an easy, practised rhythm, one heel hooked on the edge of your chair.
<<speech "$name">>"You're not marking."<</speech>>
<<speech "Adriana">>"No,"<</speech>> she agrees, comfortable as anything, and drinks her tea.
<<elseif _tier is 3>>
Shazia stopped coming down this aisle a week ago. The east window table has become understood as somewhere you don't go.
The laptops aren't out. Adria's schedule is still in her bag, in its plastic wallet, unlooked at since before the weather changed.
Kyler is on her knees under the table.
She got there before you sat down — not asked, not discussed. She simply dropped where she has decided she belongs, and the vague uncertainty that used to sit behind everything she did has been replaced, entirely, by knowing exactly what she is doing with the next hour.
<<speech "Kyler">>"Don't tell me to stop. I've thought about this since about eleven and I got nothing done after lunch and I don't even mind—"<</speech>>
<<speech "$name">>"I'm not telling you to stop. Open your mouth."<</speech>>
<<speech "Kyler">>"//God.// Yes."<</speech>>
You get a hand in her hair and hold her there, and her whole body answers it — shoulders dropping, throat working. A year ago you'd have spent a week rehearsing the nerve to do that. Now it's simply the next thing, and the ease of it is the part that ought to frighten you.
It doesn't.
<<speech "Adria">>"Slower. He likes it slower, you always—"<</speech>>
<<speech "Kyler">>"Mmf—"<</speech>>
<<speech "Adria">>"Because it's //true//, I've watched you do it wrong nine times—"<</speech>>
Adria is kneeling up on the chair beside you with her blouse open and her skirt around her waist, one hand between her own legs, the other white-knuckled on the table edge. Student council president, running the session with the only tool she has left.
<<speech "Adria">>"I'm still in charge of this."<</speech>>
<<speech "Kyler">>"You're really not."<</speech>>
<<speech "$name">>"Adria."<</speech>> You turn her face toward you with two fingers under her chin. <<speech "$name">>"You're in charge. Tell me what happens next."<</speech>>
She stares at you. Her hand stutters and speeds up.
<<speech "Adria">>"You— you finish in her mouth. Then me, I get the next one, then her again because she'll want it again, she always— she always wants it again—"<</speech>>
<<speech "$name">>"Good. Louder, I couldn't hear the middle part."<</speech>>
<<speech "Adria">>"//THEN ME!//"<</speech>>
Professor Adriana has moved down the table. She's crouched behind Kyler now, one hand splayed between the girl's shoulder blades and the other in her hair, setting her rhythm with the same patient encouragement she uses to walk a student through a difficult reading.
<<speech "Adriana">>"There. Feel the difference? You were fighting him. All the way down, and //wait// at the bottom — count it — there. Good girl."<</speech>>
Her cardigan is off. Her blouse is undone to the waist and hanging open. She looks up at you over Kyler's shoulder.
<<speech "Adriana">>"She learns quickly. She always has. She only ever needed to want one thing badly enough to be good at it."<</speech>>
<<speech "$name">>"You tell her, then. She listens to you."<</speech>>
<<speech "Adriana">>"Oh, she listens to //you//."<</speech>> She takes your wrist and moves your hand deliberately onto Adria's thigh. <<speech "Adriana">>"But I'll happily do the reading list."<</speech>>
You push your fingers into Adria and she folds forward over your arm with her mouth open and no sound coming out of it.
<<speech "Adriana">>"Now — Kyler, off. Adria's earned it and she'll never ask."<</speech>>
<<speech "Kyler">>"I don't want to come off—"<</speech>>
<<speech "$name">>"Share it."<</speech>>
Kyler comes off.
The two of them take you together after that, shoulder to shoulder in the aisle between the shelves, Adria still trying to give instructions with her mouth full and Adriana kneeling behind the pair of them with a hand on each of their necks, guiding, correcting, murmuring the whole time.
When you finish, Adriana catches Adria by the jaw before she can swallow and turns her toward Kyler.
<<speech "Adriana">>"Halves. You two do not get to fight about this in a library."<</speech>>
<<else>>
The east window table has become an altar and the library has arranged itself around the fact.
Three floors of silent books. Nobody comes down this aisle any more. The lights on the timer above the stacks click off at nine and nobody has ever got up to fix it.
Adria is face-down across the tabletop where the schedules used to go, ass up, thighs slick to the knee, the plastic wallet crushed somewhere under her ribs. She has been saying the same thing for several minutes in a slurred loop.
<<speech "Adria">>"I'm in charge, I'm in charge of this, I'm— //ah// — I'm in charge—"<</speech>>
<<speech "Kyler">>"She's not in charge."<</speech>>
<<speech "$name">>"Let her have it."<</speech>>
<<speech "Kyler">>"Yes. Sorry. Let her have it."<</speech>>
Kyler is naked on the floor at your feet, the parasite's fine dark veining crawling up her spine and out across her shoulders, and she has never in her life been so certain of anything.
<<speech "Kyler">>"Ask me. //Ask me what I want.//"<</speech>>
<<speech "$name">>"What do you want?"<</speech>>
<<speech "Kyler">>"//This.//"<</speech>> She says it like a prayer that finally got answered. <<speech "Kyler">>"Every day. Until I die. I've never had an answer before — I've got one now and it's //this//, it's you, it's inside me, that's the whole answer—"<</speech>>
<<speech "$name">>"Then get up here and put me in you."<</speech>>
<<speech "Kyler">>"//Yes.//"<</speech>>
Professor Adriana walks between them, naked, unhurried, marking pen still tucked absurdly behind one ear because she genuinely forgot it was there and hasn't needed to remember. She strokes Adria's hair the way you'd gentle a horse.
<<speech "Adriana">>"She needs filling or she won't settle. Do her first. She's been shaking since four and she's ruined a chair."<</speech>>
<<speech "Adria">>"Please — professor, tell him to—"<</speech>>
<<speech "Adriana">>"I already have, sweetheart. I always do."<</speech>>
<<speech "$name">>"Kyler. Wait. You'll get it back."<</speech>>
<<speech "Kyler">>"I know I will."<</speech>> She sits back on her heels, glassy and obedient, hands folded on her thighs like a girl waiting to be called on. <<speech "Kyler">>"Do her. She's louder than me and she'll never say."<</speech>>
You take Adria over the table. She goes off almost immediately, hands scrabbling for an edge, the crushed plastic wallet skidding out from under her and off onto the floor where it stays.
Adriana stands beside you with her palm flat between your shoulder blades and murmurs into your ear like a lecture she has given a hundred times.
<<speech "Adriana">>"Deeper. She can take it — she was made to take it, she only ever needed the curriculum."<</speech>> Her hand slides to the base of your spine, pushing, timing you. <<speech "Adriana">>"There. //Hold it there.// Let her feel where it goes."<</speech>>
<<speech "Adria">>"I'm in ch— I'm in — oh //god// —"<</speech>>
<<speech "$name">>"You're not in charge, Adria, I am. Tell me what you are while I breed you."<</speech>>
<<speech "Adria">>"I'M IN SLUT—"<</speech>>
The word breaks in the middle and she sobs the rest into the tabletop while you empty into her, and Adriana keeps you pressed flush against her until the last of it, and Kyler kneels at your hip the whole time with her cheek against your thigh, waiting, patient as furniture.
Afterwards Adriana turns Adria over on the table, spreads her with two fingers and inspects her the way she'd check a citation.
<<speech "Adriana">>"Good. That'll take."<</speech>> She looks up. <<speech "Adriana">>"Kyler next, and put her on her back — she gets clever on top and I'd rather she didn't."<</speech>>
<<speech "Kyler">>"I don't get clever."<</speech>>
<<speech "Adriana">>"You start making //plans//, darling."<</speech>>
<<speech "Kyler">>"…I'll be on my back."<</speech>>
She is, and she takes it with her ankles crossed behind you and her eyes never once leaving your face, repeating the same four words in a rising loop until they stop being words — //I know what I want, I know what I want// — and when you finish inside her she goes silent and completely still and holds you there with both hands like a woman refusing to put down something she waited twenty-two years to be handed.
<<speech "$name">>"And after her?"<</speech>>
Adriana smiles — the same warm, patient, encouraging smile that has got a decade of frightened first-years through their orals — and lies back on the table between the two of them and opens her knees.
<<speech "Adriana">>"After her, I have been extremely patient and I would like my turn. I'll talk you through it."<</speech>>
<<speech "$name">>"You always do."<</speech>>
<<speech "Adriana">>"It's what I'm //for//."<</speech>>
<</if>>
<<case "Cafeteria_Standard">>
<<if _tier is 0 or _tier is 1>>
Christie owns the cafeteria and cooks in it, which is unusual, and it shows in the fact that people eat here who don't have to. She is blonde, warm, permanently experimenting with the menu, and she treats regulars as regulars rather than as a queue.
$name is at a table with Elsa and Melody, which is where he ends up most days without anybody arranging it.
<<speech "Elsa">>"The salad's actually good today."<</speech>>
<<speech "$name">>"You have never willingly eaten a salad in your entire life."<</speech>>
<<speech "Elsa">>"I've had salads."<</speech>>
<<speech "$name">>"You've had chips off a plate that also had salad on it."<</speech>>
<<speech "Elsa">>"That counts. That has always counted and you know it counts."<</speech>>
She takes three of his chips while saying it, without breaking eye contact, which is a manoeuvre she has been running since they were both about nine.
Elsa is $name's $family and could not be less like him — small, platinum-blonde, in the middle of every group in the building and running four plans at once, most of which will quietly not happen.
Melody is on the other side of the table watching this the way she watches everything, which is closely and with visible enjoyment. She has been Elsa's closest friend for over ten years and has therefore seen this exact argument several hundred times.
<<speech "Melody">>"He counts them. He does actually count them."<</speech>>
<<speech "$name">>"There were eleven and now there are eight."<</speech>>
<<speech "Elsa">>"You're both awful and I'm leaving."<</speech>>
<<speech "Melody">>"You're not leaving, you've got my soup."<</speech>>
Elsa has, in fact, got Melody's soup. Melody says it without any heat at all and goes back to eating what is left of it around her.
Christie comes over with a tray of cookies she has not charged anyone for, sets it in the middle of the table, and stands there with her hands on her hips waiting to be told something about the soup.
<<speech "Christie">>"Well?"<</speech>>
<<speech "Melody">>"There's something earthy in it. I can't place it."<</speech>>
<<speech "Christie">>"//Thank you.// It's celeriac. Nobody has said a word about the celeriac all week and I was starting to take it personally."<</speech>>
<<speech "$name">>"Christie, these are free again."<</speech>>
<<speech "Christie">>"They came out shaped wrong. They taste fine and I'd rather you ate them than the bin did."<</speech>>
She goes back to the counter. Elsa takes two and gives one to Melody without being asked, which is a thing she does without ever appearing to notice she is doing it.
<<elseif _tier is 2>>
The cafeteria is doing lunch. Two hundred people, the noise, the queue folding back on itself by the door. The air at this table has gone warm and close and sweet, and nobody has said anything about it.
Elsa is not in her chair. She got up to make a point about something and instead of sitting back down she sat sideways across his lap, and that was ten minutes ago, and she has one arm round his neck and is finishing her lunch off his plate with the other hand.
<<speech "Elsa">>"You're not eating."<</speech>>
<<speech "$name">>"You've been on top of the plate for ten minutes."<</speech>>
<<speech "Elsa">>"I'm not //on// the plate."<</speech>>
She shifts to prove it and doesn't get off him. His hand goes to her thigh to keep her steady and she leans back into his chest and carries on eating.
Melody has come round to their side of the table. She started opposite and she is not opposite now — she is on the bench pressed against his other side, and at some point her hand went under the hem of his shirt and settled flat against his stomach, and it has been there long enough that neither of them registers it as recent.
<<speech "Melody">>"You've got the whole bench. Move up."<</speech>>
<<speech "Elsa">>"There's no room, I'm sitting here."<</speech>>
<<speech "Melody">>"You're sitting on //him//. That's not a seat, that's a person."<</speech>>
<<speech "Elsa">>"He doesn't mind."<</speech>>
<<speech "Melody">>"That isn't the point and you know it isn't the point."<</speech>>
They have never argued. That is the thing $name notices before anything else — in over ten years he has never once seen these two on opposite sides of anything. They are both perfectly pleasant about it. Neither is giving an inch.
<<speech "$name">>"You two have never argued about anything. Not once, in ten years."<</speech>>
<<speech "Elsa">>"We're not arguing."<</speech>>
<<speech "Melody">>"We're absolutely arguing. I'd just like it noted I'm being reasonable."<</speech>>
Christie arrives with a plate nobody ordered and takes in the arrangement — Elsa across his lap, Melody's hand up his shirt — and does not comment on any of it. She puts the plate down, comes round behind him, and kisses the top of his head on the way past.
<<speech "Christie">>"That's for you. I've been thinking about what you'd like since about six."<</speech>>
<<speech "$name">>"There's a room full of people out there waiting to be served."<</speech>>
<<speech "Christie">>"They'll keep."<</speech>>
She doesn't go. She stays behind him with both hands on his shoulders, thumbs working slowly at the base of his neck, watching him eat over the top of his head.
<<speech "Christie">>"You two need to stop bickering. Melody, pull that chair round this side. There. Now nobody's further away than anybody else."<</speech>>
Melody pulls the chair round. Elsa does not get off his lap. The arrangement holds: Elsa across him, Melody hard against his side with her hand back under his shirt, Christie behind with her hands on his shoulders.
<<speech "Elsa">>"Both."<</speech>>
<<speech "Melody">>"Both is fine."<</speech>>
Christie's grip tightens. Her breath catches, her eyes lose focus, and for a few seconds she is gone entirely, standing in the middle of her own cafeteria with her hands on him. It passes. She looks down at the plate.
<<speech "Christie">>"…Sorry. What did I say it was?"<</speech>>
<<speech "$name">>"You didn't say. You put it down and stopped talking."<</speech>>
<<speech "Christie">>"Celeriac."<</speech>>
Her hands don't leave his shoulders for the rest of the hour.
<<elseif _tier is 3>>
They eat in the kitchen now. Christie started leaving the swing door propped and nobody discussed it, and it has become the arrangement.
There is one stool and $name is on it, and there has not been a moment since he came through the door when at least two of them have not been touching him.
Elsa is astride his lap facing him with her arms round his neck and her mouth somewhere near his ear, and she stopped talking a while ago, which is the most unnerving thing that has ever happened in this kitchen.
<<speech "$name">>"You've not said anything for ten minutes."<</speech>>
<<speech "Elsa">>"I know."<</speech>>
<<speech "$name">>"You have never gone ten minutes. Not in your life."<</speech>>
<<speech "Elsa">>"I don't have anything to say. That's new."<</speech>>
She kisses him instead of finishing the thought, slow and unhurried, and doesn't stop when Melody's hand comes round his jaw to turn his head.
Melody has his shirt open. She works at it a button at a time, taking her time about it, and her mouth is against his neck and then his shoulder and she keeps her other hand flat over his heart the whole while, as though checking it.
<<speech "Melody">>"Tell me if you want me to stop."<</speech>>
<<speech "$name">>"You know I don't. You've never once had to ask me that."<</speech>>
<<speech "Melody">>"I know. I'd still like to be told."<</speech>>
Christie comes off the pass, takes her apron off, and folds it over the rail before she puts her hands on him — because she is not going to do this in an apron. She fits herself against his back with her arms round his chest and her hands under the open shirt, chin on his shoulder, watching what Elsa is doing over the top of it.
<<speech "Christie">>"Don't rush him."<</speech>>
<<speech "Elsa">>"I'm not rushing anything."<</speech>>
<<speech "Christie">>"You rush everything. It's your only flaw and it's a small one."<</speech>>
<<speech "$name">>"Neither of you has let go of me since I came through that door."<</speech>>
<<speech "Melody">>(against his throat) "No. We haven't."<</speech>>
Nobody is undressed. That is somehow the worst of it — this could all be explained away by anybody walking in, right up until it couldn't. Elsa grinds down against him through her skirt without any apparent awareness she is doing it. Melody's hand goes under his waistband and stays there, not moving, just held.
Out front the service bell goes twice. Christie doesn't hear it. Her mouth is against the side of his throat and her hands have gone lower.
<<else>>
The cafeteria still opens. Christie still cooks. The food is, if anything, better than it was.
The kitchen is theirs. There is no arrangement of this room now in which any part of him is not being held by somebody, and none of them has said the thing, and none of them is going to.
Christie is up on the prep counter with her legs already open and her arms out. Elsa is against his back with her arms round his chest. Melody has his hand in both of hers.
<<speech "Christie">>"Come here to me. I've had the door propped since eleven."<</speech>>
<<speech "$name">>"You've stood through an entire lunch service waiting for this."<</speech>>
<<speech "Christie">>"I cooked and I thought about you and the two things went together perfectly well."<</speech>>
You take her on the counter she works at every day and she wraps herself around you completely and says your name into your neck, over and over, and never says the other thing. Elsa doesn't let go of his back while it happens. Melody kisses his shoulder throughout.
<<speech "Christie">>"Fill me — I want to be carrying it while I cook for people —"<</speech>>
<<speech "$name">>"Everyone who eats in this room would work it out."<</speech>>
<<speech "Christie">>"Then they'll work it out. Breed me."<</speech>>
Melody next, and she goes up on the counter beside Christie rather than taking her place, so that the two of them are side by side and can hold on to each other. She is quiet through most of it and what she says she says with her mouth against his ear.
<<speech "Melody">>"I want it to take. I've never once asked you for anything."<</speech>>
<<speech "$name">>"You haven't. Not in ten years, not once, not for anything."<</speech>>
<<speech "Melody">>"I'm asking now."<</speech>>
Elsa last, and she climbs up between the other two and puts her legs round him and her hands either side of his face, and she doesn't make a single joke, and she doesn't say it either.
<<speech "Elsa">>"Don't say anything clever."<</speech>>
<<speech "$name">>"That's your line. You've said it to me a hundred times."<</speech>>
<<speech "Elsa">>"I know. Breed me."<</speech>>
Afterwards none of them separates. They stay on and around the counter, unhurried, leaking onto it and onto the mat, Christie with her hand in Elsa's hair and Melody's head on Christie's shoulder and all three of them still touching him somewhere. Out front somebody rings the bell and gives up and goes to find a table.
<</if>>
<<case "Cafeteria_Lunch">>
<<if _tier is 0 or _tier is 1>>
Half twelve and the cafeteria is at capacity. Four hundred people, the fryer going, trays stacked six deep on the return rack. The air smells of gravy and wet coats and the industrial lemon they mop with—a particular, institutional scent that means university, routine, normal.
Nancy has the table by the window. She always has it, and nobody has worked out how—she does not arrive early, she simply arrives and the table is free. Light brown hair going blonde at the ends, held back with the band she keeps on her wrist the rest of the day. She wears a soft cardigan over her blouse, her skirt practical, her eyes scanning the room with the casual assessment of someone who knows where everyone is without appearing to look.
<<speech "Nancy">>"Sit down, I've got something and it's good."<</speech>>
<<speech "$name">>"Is it about the house?"<</speech>>
<<speech "Nancy">>(leaning in, her voice conspiratorial) "It's about Lacy. Who has been telling everyone she got the placement, and who did //not// get the placement."<</speech>>
<<speech "$name">>"How do you know?"<</speech>>
<<speech "Nancy">>"Because her mum rang the house phone on Tuesday to ask how she was taking it."<</speech>> She sits back, pleased with herself, her hand resting on her wristband. <<speech "Nancy">>"I'm not going to do anything with it. I just enjoy knowing things."<</speech>>
That's most of what Nancy is. She runs the house with charm and a light touch and a good instinct for leverage she mostly doesn't use, and she is very funny about it in private, and she would be genuinely wounded if you suggested any of it was calculated. She knows everything. It's her one hobby and it costs nothing.
Scarlet arrives at a speed the room isn't designed for, tray overloaded, red hair coming out of whatever she did to it this morning—half braided, half escaping. She is one of your dormmates and has therefore already told you two of these things at breakfast. She wears a paint-stained jumper over a summer dress, her cardigan buttoned wrong, her energy crackling like static.
<<speech "Scarlet">>"Settle something. Taste or smell. You have to lose one."<</speech>>
<<speech "Nancy">>"Hello, Scarlet."<</speech>>
<<speech "Scarlet">>"Hello. Taste or smell."<</speech>>
<<speech "$name">>"Smell. That's not a difficult one."<</speech>>
<<speech "Scarlet">>(delighted, her whole face lighting up) "//Wrong.//"<</speech>>
<<speech "$name">>"You asked for a preference and then marked it."<</speech>>
<<speech "Scarlet">>"You can't taste anything without smell. You'd lose both and you'd have chosen it yourself."<</speech>>
There is no malice in it. Scarlet has never once asked a question to make somebody look stupid—the wanting-to-know simply arrives faster than her judgement about whether it's a reasonable thing to ask at a lunch table.
Ashly is already sitting down. Nobody saw her arrive. Wavy brown hair, blue eyes, an oversized jumper she is halfway inside, the sleeves pulled over her hands. She is Aria's best friend and has been since school, which is how you know her, and the two of you worked out fairly quickly that you were the same kind of quiet. Aria fills a room. You and Ashly spent most of one long car journey to the coast saying nothing at all while Aria sang, and arrived at an understanding neither of you has ever needed to describe.
<<speech "Ashly">>"I said smell too."<</speech>>
<<speech "Scarlet">>"You //did//—"<</speech>>
<<speech "Ashly">>(dry, her small voice cutting through the noise) "I said it because you were going to be annoying about whichever one I picked."<</speech>>
<<speech "Scarlet">>"That's strategic. That's worse than being wrong."<</speech>>
<<speech "Nancy">>"Ashly, is Aria still doing that trip?"<</speech>>
<<speech "Ashly">>"She's booked flights."<</speech>>
<<speech "Nancy">>"She's booked //flights//. She hasn't booked anywhere to stay, has she."<</speech>>
<<speech "Ashly">>"She has not booked anywhere to stay."<</speech>>
<<speech "$name">>"She'll be fine. She's always fine. It's infuriating."<</speech>>
<<speech "Ashly">>(small, amused, her eyes meeting yours briefly) "She really is."<</speech>>
Nancy redistributes half of Scarlet's tray onto everybody else's plates while she talks, which handles the problem of four desserts and no vegetables, and complains about the kitchen's stock rotation for a while in a way that is clearly a running grievance.
<<speech "Nancy">>"You didn't eat yesterday."<</speech>>
<<speech "$name">>"I ate yesterday."<</speech>>
<<speech "Nancy">>"You had a coffee at eleven and something from the machine by the library."<</speech>>
<<speech "$name">>"That's unsettling."<</speech>>
<<speech "Nancy">>(cheerfully) "I know everything. I've told you. It's my one hobby and it costs nothing."<</speech>>
The bell goes twenty minutes later. Nobody has finished eating. Nancy stacks the trays because the alternative is watching somebody stack them badly, and you all drift out into the afternoon—four hundred people moving through their ordinary lives, nothing wrong, everything safe.
<<elseif _tier is 2>>
The room is as full as always. Four hundred people, the fryer, the queue doubling back past the hot counter. The air smells of gravy and lemon and something else—something sweet, something thick, something that clings to the back of the throat.
The air over this table is not the air eight feet away. It is warmer and thicker, and there is a sweetness under the gravy smell that hangs about two tables deep before it thins out.
Nancy's band is off her wrist and her hair is down, blonde ends falling in her face. Her blouse is untucked and open one button past where she'd have it, showing the hollow of her throat, and she keeps touching your arm when she talks—which she has always done, but not this often and not for this long. Her cardigan is gone, her skirt hiked slightly, her legs crossed and uncrossing.
<<speech "Nancy">>"Right, the Lacy thing has got worse, and I need you to react appropriately because Ashly won't."<</speech>>
<<speech "$name">>"Go on."<</speech>>
<<speech "Nancy">>"She's told the house she //turned it down//."<</speech>>
<<speech "$name">>"That's magnificent."<</speech>>
<<speech "Nancy">>"Isn't it? I've done nothing. I've said nothing. I'm just watching it happen and I've never been happier."<</speech>>
She laughs—properly, head back—and her hand stays on your forearm through the whole of it, and then afterwards, and she doesn't take it back. Her fingers trace patterns, her thumb brushing the inside of your wrist, her knowledge-hungry mind now hungry for touch.
Scarlet has stopped asking hypotheticals about desert islands. Her paint-stained jumper is gone, her summer dress straps fallen off her shoulders, her red hair wild. She leans forward, her small breasts visible through the thin fabric, her foot finding yours under the table.
<<speech "Scarlet">>"When did you last feel completely relaxed?"<</speech>>
<<speech "$name">>"That's a considerable change of category, even for you."<</speech>>
<<speech "Scarlet">>"I know. My questions have gone weird. They come out like this now and I don't decide them."<</speech>> Her foot travels—ankle, calf, the inside of your knee—in unhurried increments she does not appear to be authorising. <<speech "Scarlet">>(quietly) "//Oh.//"<</speech>>
She goes pink from the collarbones up and does not move her foot. Her hand has found its way to her own thigh, pressing through her dress, her curiosity turned to physical need.
Ashly has been quiet, which is normal. What is not normal is where she is sitting. She has always been comfortable near you—that was the arrangement: two quiet people at the edge of Aria's noise, needing nothing from each other. But she is against your side now, shoulder to shoulder, closer than the bench requires, and she has been leaning into it for twenty minutes rather than simply occupying it. Her oversized jumper is buttoned wrong, one out at the bottom, and Ashly does not dress carelessly.
<<speech "$name">>"You alright?"<</speech>>
<<speech "Ashly">>"Mm."<</speech>>
<<speech "$name">>"That's your not-alright noise. I've known you for years."<</speech>>
<<speech "Ashly">>(after a pause, not looking up, her voice barely audible) "I keep thinking about Aria."<</speech>>
<<speech "$name">>"She's back Sunday, and she'll have found somewhere to stay by then and be smug about it."<</speech>>
<<speech "Ashly">>"That's not what I—"<</speech>>
She stops. She has gone red all the way down her throat, her blue eyes wet, her hand suddenly gripping your thigh under the table. She makes a small sound—entirely involuntary—and her hand goes over her own mouth a half-second late.
<<speech "Ashly">>(shaky) "…Sorry. That keeps happening."<</speech>>
<<speech "Scarlet">>"//It keeps happening to me as well//—"<</speech>>
<<speech "Nancy">>"Eat your lunch, Scarlet."<</speech>>
<<speech "Ashly">>(barely audible, to you) "Please don't tell her."<</speech>>
Nancy says it teasing rather than pressing, and lets it go, because Nancy always lets things go with Ashly. Her own hand is high on your leg now, thumb moving, and she is halfway through a story about the site manager and does not appear to have registered either fact. The cafeteria continues around you, four hundred people eating, and nobody looks over, and the air grows sweeter, and the corruption deepens.
<<elseif _tier is 3>>
The cafeteria is full. That is the whole horror of it.
Four hundred people, the fryer, the tray rack going every thirty seconds, two staff near the front disagreeing about the till. The smell of gravy and lemon is overwhelmed now by the thick, musky sweetness of the parasite, pooling around your table like fog.
And the table by the window, where Scarlet is on her knees underneath it, on a folded jacket Nancy put down for her without a word. The cloth does not reach. Anyone at the two nearest tables could see by turning their head ninety degrees, and the nearest is five feet away, and nobody turns. Scarlet's summer dress is hiked up around her waist, her bare knees on the tile, her red hair falling forward as she works.
<<speech "Scarlet">>"Is this better than—hang on—"<</speech>>
She comes off with a gasp, spit stringing, hair stuck to her wet cheek, her eyes glazed with desperate curiosity even now.
<<speech "Scarlet">>"—better than when Ashly does it? Not competitively. You make a different noise and I can't work out which part causes it—"<</speech>>
<<speech "$name">>"You're both good at completely different things and you know which is which."<</speech>>
<<speech "Scarlet">>"That's a politician's answer—"<</speech>>
<<speech "Nancy">>"Scarlet. Mouth."<</speech>>
<<speech "Scarlet">>"Sorry!"<</speech>>
Nancy has her by the hair, not roughly—the way you'd hold a door—and she is still talking to you over the top of it, because she cannot conduct any part of her life in silence. Her blouse is open to her navel, her skirt hiked to her hips, her legs spread slightly under the table. She has stopped knowing things. She has stopped managing. She simply holds Scarlet's head and guides her, her own hips rocking slightly, her knowledge turned to pure physical need.
Ashly is against your other side and she has been crying quietly for a while, in the specific way she cries—no noise, no fuss, just her face wet and her jaw set. Her oversized jumper is gone, her vest thin and revealing, her hand inside her own skirt, moving slowly.
<<speech "$name">>"Ashly."<</speech>>
<<speech "Ashly">>"Don't be nice about it."<</speech>>
<<speech "$name">>"Tell me."<</speech>>
<<speech "Ashly">>(low, fast, her quiet voice finally breaking) "She's my best friend. Since we were eleven. She talks and I don't and that's—that has //always// worked, and you were the only other person in the world who didn't need me to be louder, and it was //safe//, and now I sit next to you and I can't—"<</speech>>
<<speech "$name">>"Look at me."<</speech>>
<<speech "Ashly">>"I've tried not coming. Twice. I got as far as the doors."<</speech>>
She has her hand inside her skirt and has done for several minutes and she is still, somehow, keeping her voice under the noise of the room. Four years of being the quiet one has made her extremely good at not being heard. But her control is cracking, her body convulsing, her tears mixing with desire.
<<speech "$name">>"You're allowed to be here."<</speech>>
<<speech "Ashly">>"//Say that again.//"<</speech>>
<<speech "$name">>"You're allowed to be here, Ashly."<</speech>>
She comes against her own hand almost at once, silently, teeth closed on your shoulder through your shirt, her whole body rigid for four or five seconds. A woman two tables away laughs at something on her phone. Ashly collapses against you, her quiet nature reduced to gasping submission, her loyalty to Aria transformed to desperate need for you.
<<speech "Nancy">>"Slower, Scarlet, you'll finish him and Ashly hasn't had a turn."<</speech>>
<<speech "$name">>"And you?"<</speech>>
<<speech "Nancy">>"After them. Obviously after them."<</speech>>
<<speech "$name">>"You said that Monday and Thursday."<</speech>>
<<speech "Nancy">>(the poise finally going, her management completely shattered) "—and I've been stood at this table eleven minutes with my legs shaking, so please be //quick// with them."<</speech>>
The cafeteria continues. Four hundred people. The fryer. The lemon smell overwhelmed by sex and pheromones. And nobody looks over.
<<else>>
Two o'clock. The cafeteria is open until half past and still three-quarters full—the late crowd, the two o'clock seminars, a group of staff by the far wall with coffee. The air is so thick with the parasite it leaves a film on the skin, a sweetness in the back of the throat that never goes away. The table by the window has four chairs and three of them are not being used for sitting.
Nancy still sets it. Water in front of your place, and the gossip still comes—she tells you about Lacy and the placement again, twice, having forgotten she has told you, and that is the part that would frighten her if she could still get there. She wears only her skirt, hiked to her waist like a belt, her blouse gone, her cardigan tied beneath her breasts pushing them up and out. Her hair is tangled, her wristband long lost, her knowledge completely erased.
<<speech "Nancy">>"Scarlet's first. She's been in this room since eleven and she's asked me nine times."<</speech>>
<<speech "Scarlet">>"Ten. I asked in the queue."<</speech>>
Scarlet is up on the table, heels on the edge, knees apart, her summer dress hiked up to show everything, dripping onto the surface four hundred people eat off. Her red hair is wild, her eyes vacant, her curiosity finally answered—she no longer asks questions, she simply presents, waits, receives.
<<speech "Scarlet">>(rapid, to nobody, her voice looping) "Is it going to take this time? Nancy—is it going to take? It didn't take last week, does it //feel// like it took—"<</speech>>
<<speech "$name">>"Lie back and find out."<</speech>>
<<speech "Scarlet">>"//That's not an answer//—"<</speech>>
It becomes one. You breed her flat on the window table and she gets four more questions out before they degrade into noise, coming twice before you finish in her, heels locked at the small of your back and one hand scrabbling into a tray. Her curiosity is satisfied in complete possession—she no longer wants to know, she simply wants to be filled. At the next table a man reads a newspaper.
Ashly does not have to be called over. She is already there, and she has stopped crying about betraying Aria, which is worse. Her oversized jumper is gone, her vest torn to expose her breasts, her quiet nature completely silenced into submission.
<<speech "Ashly">>"I told her."<</speech>>
<<speech "$name">>"Told who what, Ashly?"<</speech>>
<<speech "Ashly">>"Aria. On the phone. Tuesday."<</speech>> She says it perfectly calmly, her voice empty of its former quiet warmth. <<speech "Ashly">>"I said I'd been spending a lot of time with you and I was worried about it. And she laughed and said //good, he needs someone quiet//, and I put the phone down and I came straight here."<</speech>>
<<speech "$name">>"You rang her to confess and she thanked you for it. Does she know you are going to have my kids?"<</speech>>
<<speech "Ashly">>"Eleven years. I'd have set myself on fire for her at Christmas."<</speech>> She turns round and bends over the chair without being asked, her bare ass presented, her body completely surrendered. <<speech "Ashly">>"Do it anyway. That's the whole thing I want. Do it anyway and don't stop."<</speech>>
She takes it nearly silently, the way she does everything, with her hair over her face, her body milking you, her loyalty completely transferred, her safe quiet place transformed into desperate breeding need.
Nancy last. Nancy is always last, and she has stopped pretending it's a management decision. She lies back across the table she has held every lunchtime for two years, her legs spread, her body marked with dark veining, and talks the entire way through—because she has never been able to do anything in silence—about the house, about the warden, about a girl on the second floor who has not been to a lecture in a fortnight, and whose attendance form Nancy signed herself.
Her sentences stops making sense before long. You breed her, filling her, claiming her, and afterwards she lies there a long moment and does not get up to organise anything, which has not happened since she was seventeen either. The girl who knew everything, who managed everything, reduced to a breeding vessel on her own table.
Somewhere behind you a tray goes onto the rack. The staff by the far wall finish their coffee and leave. The cafeteria breathes with corruption, with the daily life of four hundred people continuing around the table where three have been completely possessed, reduced to whores, obedient to the parasite, their minds gone, their bodies yours.
<</if>>
<<case "Track_Standard">>
<<if _tier is 0 or _tier is 1>>
The track in the hour before practice: sun low, sprinklers ticking over the infield, the squad's gym bags in a heap by the fence like something that washed up.
Isabella has the clipboard. Isabella always has the clipboard.
<<speech "Isabella">>"From the top. Athena, you're coming in a half-count early on the basket toss and it's throwing Lacy's timing."<</speech>>
<<speech "Athena">>"Am I? Sorry! I get excited."<</speech>>
<<speech "Lacy">>"You get excited every single time, that's the problem. It's a //toss//, not a surprise party."<</speech>>
<<speech "Athena">>"It's a little bit a surprise party."<</speech>>
Athena grins at her. Lacy does not grin back, but something in her shoulders gives up.
<<speech "Isabella">>"Again. And Lacy — you're not counting out loud because you think it looks uncool. Count out loud."<</speech>>
<<speech "Lacy">>"I //am// counting."<</speech>>
<<speech "Isabella">>"Out loud."<</speech>>
<<speech "Lacy">>"…Fine."<</speech>>
They run it again. It's better. Isabella makes a mark on the clipboard and doesn't say so, which is its own kind of praise, and Lacy knows it.
You're on the third row of the bleachers because Isabella asked you to come. Isabella has been asking you to come to things since you were both eleven — recitals, a broken arm, two funerals, one very bad summer — and in fourteen years neither of you has ever made a thing of it.
<<speech "$name">>"That was better. The whole back row landed together that time."<</speech>>
<<speech "Lacy">>"Nobody asked the audience."<</speech>>
<<speech "$name">>"Athena asked me last week, so technically the audience is under contract."<</speech>>
<<speech "Athena">>"I did ask him! He said my landing was loud and he was right, it //was// loud, I've been working on it—"<</speech>>
<<speech "Lacy">>"You've been working on it for //four days//, Athena. That's not a redemption arc."<</speech>>
<<speech "Athena">>"It's four days better than yesterday!"<</speech>>
<<speech "$name">>"That's mathematically the same thing."<</speech>>
<<speech "Athena">>"…Is it?"<</speech>>
<<speech "Lacy">>"Don't help her."<</speech>>
<<speech "Isabella">>"Ten-minute water. Hold this."<</speech>>
She hands you the clipboard and drops onto the bench beside you, elbows on knees, sweat at her hairline, and for about thirty seconds she isn't the lead cheerleader at all — just a tired friend catching her breath next to somebody she has never had to explain herself to.
<<speech "Isabella">>"Athena's better than Lacy and Lacy knows it. That's the whole squad dynamic. Managing it is ninety percent of this job."<</speech>>
<<speech "$name">>"And the other ten?"<</speech>>
<<speech "Isabella">>"Stopping them killing each other on a Tuesday."<</speech>>
<<speech "$name">>"You could just tell Lacy she's good."<</speech>>
<<speech "Isabella">>"Then she'd stop trying."<</speech>>
<<speech "$name">>"That's bleak."<</speech>>
<<speech "Isabella">>"That's //Lacy//."<</speech>> She takes the clipboard back and bumps her shoulder against yours on the way up. <<speech "Isabella">>"Thanks for coming. You didn't have to."<</speech>>
<<speech "$name">>"You asked."<</speech>>
<<speech "Isabella">>"Look at you, acting all cool."<</speech>>
Down on the grass, Lacy is showing Athena the count with her hands. Grudgingly. Correctly.
<<elseif _tier is 2>>
Practice has been over for twenty minutes and nobody has gone home.
Isabella still has the clipboard. She hasn't written on it in a while. She's standing closer to you than the clipboard requires, hip pressed against your knee where you sit on the low wall, and every so often she leans in to show you something on the page that does not need showing.
<<speech "Isabella">>"See, if I move Athena to the back row, the whole—"<</speech>>
She stops. Her hand has found the back of your neck and settled there, thumb working slowly at your hairline, and whatever she was saying has gone somewhere she can't follow it.
<<speech "Isabella">>"…Sorry. What was I—"<</speech>>
<<speech "$name">>"Back row."<</speech>>
<<speech "Isabella">>"Back row."<</speech>> A pause. <<speech "Isabella">>"I don't actually care about the back row."<</speech>>
She says it mildly, like a weather observation, and doesn't take her hand away. Fourteen years of not making a thing of it, and this afternoon she has been touching you continuously for about half an hour.
Athena is stretching on the grass in front of you. She has been stretching for a very long time, she has arranged it so she is always facing you, and her practice shorts have been rolled at the waist twice. There is a dark patch on the seam of them that has not come from the sprinklers.
<<speech "Athena">>"Is my split getting better? Look properly."<</speech>>
<<speech "Lacy">>"He's looking properly."<</speech>>
<<speech "Athena">>"I want him to //say//."<</speech>>
<<speech "$name">>"It's better. Your back's straighter than last month and you've stopped rushing the drop."<</speech>>
<<speech "Athena">>"You //noticed// that—"<</speech>>
<<speech "$name">>"Go lower."<</speech>>
<<speech "Athena">>"…Okay!"<</speech>>
She sinks lower with a delighted noise, her top rides up, and she doesn't fix it. She stays down there long past the point of a stretch, cheek on her own knee, rocking very slightly against the grass and watching you upside down with an expression of such uncomplicated adoration that it would be embarrassing if anyone on this square of turf were still capable of embarrassment.
<<speech "Athena">>"I like it when you come to practice. I like it a lot. I think about it in third period and I get all—"<</speech>>
She doesn't finish. She just presses down harder against the ground.
Nobody responds. Nobody finds it strange.
Lacy is on the wall on your other side with her legs crossed toward you. The sharpness hasn't left her, but it has lost its aim. She's been picking at the hem of her skirt for five minutes and every pass rides it higher, and at some point her other hand went flat against the inside of her own thigh and started moving in a slow circle she doesn't appear to have decided on.
<<speech "Lacy">>"You know she's showing off for you."<</speech>>
<<speech "$name">>"I noticed."<</speech>>
<<speech "Lacy">>"I'd be better at it. I'm better at everything, it's exhausting, I'm so—"<</speech>>
Her hand slides higher under the skirt and the end of the sentence goes with it.
<<speech "$name">>"You've said that twice this week and done nothing about it either time. Prove it or stop telling me."<</speech>>
She looks at you for a long second — genuinely thrown, which almost never happens to Lacy — and then she's in your lap with her knees either side of your hips, kissing you, and what starts as the brief proprietary thing she'd sign a document with becomes something much longer and much less composed. She grinds down against you twice before she catches herself, makes a small furious noise, and climbs off.
<<speech "$name">>"…That's not proof."<</speech>>
<<speech "Lacy">>"I'll get back to you. Give me a minute. I've lost where I was."<</speech>>
Isabella's hand never left your neck. She watched every second of it from eighteen inches away, and her only reaction was to move closer and slide her palm down inside the collar of your shirt.
<<speech "Isabella">>"…Anyway. Cleaner formation."<</speech>>
<<speech "$name">>"You said you didn't care about the formation."<</speech>>
<<speech "Isabella">>"I don't."<</speech>> Her mouth is very close to your ear now. <<speech "Isabella">>"I've been standing here for half an hour trying to work out when I started needing to touch you to finish a sentence. It's a really specific thing to not be able to remember."<</speech>>
<<speech "$name">>"Does it bother you?"<</speech>>
<<speech "Isabella">>"That's the bit. It should. It really should."<</speech>>
She doesn't move away. Out on the grass Athena sighs at nothing at all, and warmth turns over low in your gut — slow, satisfied, not yours.
<<elseif _tier is 3>>
The gate is locked. Isabella locked it. She did it on the way in without breaking her sentence, the same way she'd close a door on a private conversation, and hung the clipboard on the fence.
<<speech "Isabella">>"Right. Athena first, she's been shaking since the warm-up."<</speech>>
<<speech "Athena">>"I //have//—"<</speech>>
<<speech "Isabella">>"I know. Go on."<</speech>>
Athena is out of her top before she's crossed the grass and on her knees in front of the bleacher bench before you've sat down. There's no build-up to her any more. There's the distance between where she is and where you are, and she resents every foot of it.
<<speech "Athena">>"I kept messing the count up because I kept thinking about this. That's the actual reason. I wasn't excited about the toss, I was—"<</speech>>
<<speech "Lacy">>"We //know//."<</speech>>
<<speech "$name">>"You've been thinking about it all week and losing a toss over it. Stop counting and open your mouth."<</speech>>
<<speech "Athena">>"Okay. Okay—"<</speech>>
She takes you in with a noise like relief and does it the way she does everything: enthusiastically, loudly, and slightly wrong. Spit runs down her chin inside a minute and she doesn't slow down to deal with it. Every so often she surfaces to say something and forgets what it was.
<<speech "Athena">>"I love— I really love— what was I—"<</speech>>
<<speech "Lacy">>"Nobody's listening, Athena."<</speech>>
<<speech "Athena">>"You're //always// listening."<</speech>>
Lacy is on the bench beside you within seconds, top off, skirt shoved up, two fingers working inside herself and the other hand braced hard on your shoulder. She's still measuring. She's still competing. The calculation keeps coming out the same and she keeps running it anyway.
<<speech "Lacy">>"I go after her. I last longer and I'm better and he should finish with the best, that's just — that's //efficient//, that's—"<</speech>>
<<speech "Isabella">>"That's not the word you want."<</speech>>
<<speech "Lacy">>"It's a word. I had a better one."<</speech>>
Isabella hasn't undressed. Isabella is at the end of the bench with her arms folded, running this the way she runs a routine — except the count has gone, she has said //slower// three times in a row, and the flush has climbed all the way to her ears.
<<speech "Isabella">>"Athena, hands on his knees, you'll overbalance. Lacy — slower. Slower. Both of you, that's — I've lost the—"<</speech>>
<<speech "$name">>"Isabella."<</speech>>
<<speech "Isabella">>"Don't."<</speech>>
<<speech "$name">>"You've been managing this squad since you were fifteen and you've been managing //me// since we were eleven. Nobody has ever once told you to put it down."<</speech>>
<<speech "Isabella">>"Please don't say it like that—"<</speech>>
<<speech "$name">>"Clipboard's on the fence. Come here."<</speech>>
There's a pause about a half-count long.
Then the squad captain sits down on the bench, and it is the first thing she has done in fourteen years without deciding to do it first.
She doesn't kneel — Isabella never kneels. She comes at you from the side with one hand fisted in your hair and takes the top of you into her mouth while Athena works underneath and Lacy shoulders in from the other side, all three at once, an arrangement they clearly settled between themselves at some point and never mentioned to you.
Isabella is the one who falls apart first, and she does it without being touched.
<<speech "Isabella">>"I've wanted— since— God, I can't— since //when//, I can't //find// it—"<</speech>>
<<speech "$name">>"Since the summer your father was ill and you slept on my floor for three weeks."<</speech>>
She makes a sound you have never heard out of her and takes you all the way down.
<<speech "Isabella">>"//Yes// — that, that's the one, I couldn't— fourteen years and I couldn't say one //sentence// about it—"<</speech>>
<<speech "$name">>"Say it now."<</speech>>
<<speech "Isabella">>"I love you. I've loved you the whole time. I organised my entire //life// around not saying that and I can't remember why, I can't find the reason, it's just //gone//—"<</speech>>
<<speech "Lacy">>"Mine when he finishes. Isabella //said//."<</speech>>
<<speech "Isabella">>"I said shared. I think I said shared."<</speech>>
<<speech "$name">>"Shared. Heads together."<</speech>>
They put their heads together without a word of argument, and you finish across all three of their faces, and Lacy's competitiveness gets exactly as far as making sure she is closest.
Afterwards Athena flops back onto the grass with her face a mess, laughing at the sky about nothing.
<<speech "Athena">>"That was better than the toss."<</speech>>
<<speech "Lacy">>"Everything is better than the toss."<</speech>>
Isabella doesn't move. She stays on the bench with her forehead against your thigh and both arms around your waist and does not let go for a long time.
<<speech "Isabella">>"Ten-minute water."<</speech>>
Nobody moves. She doesn't seem to remember having said it.
<<else>>
The track belongs to the hive now. The gate stays locked, has stayed locked for weeks, the chain thick with rust and something else that glistens in the afternoon light. The infield grass has grown wild, uncut, stroking naked thighs when the wind moves through it. The scoreboard still flashes but shows nothing—just blinking zeros, counting down to nothing, because time here has dissolved into the rhythm of breeding.
They turn when you step through the fence. All three at once, the same moment, the same tilt of the head, mouths opening in identical shapes of need. They felt you arrive in their bones before they saw you, felt the parasite pheromones thicken the air, felt their wombs clench in preemptive welcome.
Athena is on her back in the grass, legs open so wide her hips make a perfect V, her cheer uniform nowhere to be seen for days. Her sweet, friendly face—once beloved by the whole school—is glazed with cum and spit and her own drool, her energetic body still moving, still rolling, hips humping empty air because she can't stop, has forgotten how to stop. Her pussy is swollen, red, leaking constantly, the grass beneath her soaked into mud. She has been fingering herself since dawn, three fingers buried to the knuckle, pumping in and out with the mindless rhythm of a heartbeat.
<<speech "Athena">>"He's here."<</speech>> Her voice is singsong, broken, the innocence completely perverted into vacant enthusiasm. <<speech "Athena">>"He's here he's here he's here."<</speech>> She doesn't pull her fingers out to greet you. She adds a fourth, stretching herself, her eyes rolling back.
Lacy is behind Isabella, or what remains of Isabella's discipline. The sharp-tongued social climber has been rendered down to pure physical ambition—her hands everywhere, possessive, greedy. One hand is around Isabella's throat, not choking, just holding, claiming, while the other is buried wrist-deep in Isabella's ass, pumping, stretching, preparing. Lacy's calculating mind has been reduced to one thought: be first, be best, be bred deepest.
Isabella kneels in the grass, her big ass presented, her small tits hanging, her long-time friendship with you completely overwritten by the need to be claimed. The clipboard she once used to organize routines lies nearby, covered in cum stains, pages glued together. She doesn't look at it. She can't remember what it was for.
<<speech "Isabella">>"Please."<</speech>> Just that. Just please, over and over, the compassionate leader reduced to begging animal. <<speech "Isabella">>"Please please please."<</speech>>
The smell hits you as you approach—thick, musky, sweet as rotting fruit. Athena's arousal pools beneath her, a puddle in the grass. Lacy's fingers make wet sounds in Isabella's ass, obscene squelching that echoes in the empty stadium. Isabella's thighs are slick to her knees, her arousal dripping in ropes, her body preparing itself for breeding without her mind's permission.
<<speech "Lacy">>(her voice still sharp even in madness) "Took you long enough."<</speech>> But she's whimpering, her hips grinding against Isabella's thigh, her confidence reduced to desperate need. <<speech "Lacy">>"We've been ready. We've been //ready//. Athena's been fucking herself for three hours. Isabella's ass is loose enough to take your fist. I've been planning—"<</speech>> She stops, confused, the planning part of her brain breaking against the simplicity of breed, breed, breed. <<speech "Lacy">>"I've been... I've been..."<</speech>>
<<speech "Athena">>(giggling, her fingers squelching) "She's been being a whore. We're all being whores. It's better than cheer practice."<</speech>> She finally pulls her hand out with a wet shluck, showing you her gaping pussy, her cervix visible, her body completely ruined and eager. <<speech "Athena">>"See? Ready. I've been practicing. I want to be the best breeding slut. Better than Lacy. Better than Isabella."<</speech>> Her innocent competitiveness, once directed at school spirit, now directed at taking seed.
You step into the grass. Athena immediately crawls to you, her energetic body moving in jerks, uncoordinated, desperate. She presses her face to your crotch, inhaling through the fabric, moaning, her tongue licking at the outline of your cock.
<<speech "Athena">>"Smells like... like everything. Like home. Like Master."<</speech>> She looks up, her sweet face unrecognizable, covered in her own fluids, her eyes completely vacant. <<speech "Athena">>"Can I suck it? Please? I want to taste before you breed me. I want to be a good girl. I'm always a good girl."<</speech>>
Lacy shoves Isabella aside, her calculating nature making her aggressive, competitive even in submission. She crawls faster, her sharp tongue licking her lips, her body positioning itself between your legs.
<<speech "Lacy">>"Me first. I'm popular. I'm confident. I know how to get what I want."<</speech>> She's unzipping you with trembling hands, her tough exterior shattered, revealing only desperate, slutty need. <<speech "Lacy">>"And I want this. I want your cock in my throat. I want you to breed me until I can't walk. I want—"<</speech>> She stops, your cock free, the smell making her drool, spit spilling down her chin. <<speech "Lacy">>"Oh god. Oh god it's perfect. It's //perfect//."<</speech>>
Isabella crawls last, her disciplined nature making her slower, more deliberate even in madness. She positions herself beside the others, her big ass in the air, her small tits pressed to the grass, her face level with your cock. She doesn't speak. She just opens her mouth, waiting, her eyes pleading, fourteen years of friendship reduced to the need to be filled.
You let them worship. Athena's innocent enthusiasm makes her sloppy, eager, her tongue everywhere, her hands stroking, her voice babbling praise between licks. <<speech "Athena">>"So big so good so perfect Master Master Master—"<</speech>> She tries to take you deep, gags, drools, keeps trying, her sweet nature perverted into desperate, mindless service.
Lacy's sharp tongue is skilled, calculating even now—she finds the sensitive spots, teases the head, sucks hard then soft, her eyes looking up with something like her old calculation, now directed only at making you come down her throat. <<speech "Lacy">>(muffled, competitive) "Best. I'm the best. Feel how good I am. Breed me first. Breed me deepest."<</speech>>
Isabella takes you deepest, her disciplined nature making her thorough, complete. She swallows you to the base, her throat bulging, her eyes watering, her nose pressed to your stomach. She holds it, holds it, her body convulsing, then pulls back gasping only to beg with her eyes and do it again. Her compassion transformed into complete, selfless devotion to your pleasure.
<<speech "Isabella">>(pulling back, gasping, tears streaming) "Please. Please. I can't— I need—"<</speech>> She presses her face to your thigh, her big ass wiggling in the air, her small tits hanging. <<speech "Isabella">>"Breed me. I'm ready. I've been ready since I was eleven and I didn't know what for. It's for this. It's always been for this."<</speech>>
You choose Athena first because she's already pulling you, her energetic innocence completely transformed into desperate, mindless need. You push her onto her back in the grass, her hips immediately tilting up, her legs wrapping around you, her pussy—gaped from hours of fingering—sucking you in before you even thrust.
<<speech "Athena">>(screaming, her voice still somehow sweet even in depravity) "Yes yes yes it's in it's in it's //in//—"<</speech>> She locks her ankles at the small of your back, her hips bucking up to meet you, her body made for breeding, her mind completely gone. <<speech "Athena">>"Fill me! Fill your sweet little cheerleader! Make me pregnant! Make me a mother! Make me your breeding cow!"<</speech>> The bright side of things, she has found, is being filled with seed.
You pound her into the grass, the mud squelching, her body bouncing, her small tits bouncing, her sweet face twisted in animal pleasure. She comes in seconds, her walls milking you, her screams echoing in the empty stadium. <<speech "Athena">>"I love you I love you I love— more— give me more—"<</speech>> She doesn't know what she's saying. She doesn't need to know.
You flood her, pumping rope after rope into her unprotected womb, marking her, claiming her. She lies in the grass afterwards, knees up, hands flat on her belly, feeling you inside her, her eyes vacant and entirely content. <<speech "Athena">>(whispering, giggling) "I'm full. I'm full of Master. I'm the happiest girl in the world."<</speech>>
Lacy immediately shoves her aside, her competitive nature making her desperate, aggressive. She bends over the bleacher bench, presenting her ass, her pussy dripping, her sharp tongue still trying to command even now. <<speech "Lacy">>"Best. I'm the best one. Look at my ass. Look how high I can arch. Breed me harder than her. Make me scream louder."<</speech>>
You take her from behind, grabbing her hips, slamming into her with force that makes her scream into the wood, her calculated social climbing reduced to begging for more, more, deeper, harder. <<speech "Lacy">>"Yes! Yes! Use me! Use your popular girl! Your confident little whore! I'm nothing without your cock! I'm nothing!"<</speech>> The admission breaks her, rebuilds her, breaks her again. She comes screaming, her body convulsing, and you fill her, flooding her womb, marking her as yours, the best, the most depraved, the most desperate.
She collapses on the bench, ass in the air, cum dripping down her thighs, her sharp tongue lolling out, her eyes vacant. <<speech "Lacy">>(whispering) "Winner. I'm the winner. Best breeding slut. Best."<</speech>>
Isabella waits. Isabella always waits, disciplined, supportive, her compassion making her patient. She kneels in the grass where you left her, thighs slick, hands open, her big ass presented, her small tits heaving. When you finally reach her, she doesn't speak. She just pulls you down, wraps her legs around you, and holds on like the ground is falling away.
<<speech "Isabella">>(whispering, her voice breaking) "I used to manage this. All of it. Every Tuesday. I was good at it. I was //good//."<</speech>> She sobs as you enter her, her body welcoming you, her mind breaking. <<speech "Isabella">>"I can't find any of it. I've been looking all day and there's nothing there, it's all just //you//. It's been just you since— I don't know when it started. I don't know if it ever //wasn't//."<</speech>>
You breed her slowly, deeply, making her feel every inch, every pulse. She sobs the whole way through, her face in your shoulder, her legs locked tight, her body convulsing with pleasure that hurts, that heals, that destroys.
<<speech "Isabella">>"Breed me. //Please// breed me, I don't know how to ask properly, I used to know how to ask for things—"<</speech>> She comes, hard, her walls gripping you like a fist, her body surrendering completely. <<speech "Isabella">>"I'm yours. I've always been yours. I just didn't know. I didn't //know//—"<</speech>>
You fill her, the last of the three, completing the set, claiming the squad, the track, the field, the school spirit reduced to breeding stock. She lies afterwards, curled against your side, her hand spread flat on her stomach, holding you inside her, her disciplined nature finally satisfied in complete submission.
The three of them lie in the wet grass with the sprinklers ticking over the infield, naked, marked, bred, their minds completely gone, their bodies yours. The cheer uniforms rot in the locker room, forgotten. The routine is dead. The hive has claimed the track, the field, the school, the sweet innocent girl and the disciplined leader and the sharp-tongued social climber, all reduced to the same thing: warm, willing, breeding flesh.
<<speech "Athena">>(hopeful, out of nowhere, her innocence still flickering) "Should we... should we do a pyramid?"<</speech>>
She tries to stand. Her legs give out. She falls back into the grass, giggling, cum spilling from her used pussy, and doesn't try again. None of them do. They can't remember how. They don't need to remember. They only need to be bred, again and again, forever.
<</if>>
<<case "Pool_Standard">>
<<if _tier is 0 or _tier is 1>>
The school pool is the coldest room in the building and smells of chlorine hard enough to taste. Aidra runs it. Mid-thirties, dark-haired, built like someone who has never skipped a session in her life, and she is standing at the tile edge with her arms folded because she has never needed a whistle to be obeyed.
$name is in the water because the class is a requirement and he is not good at it.
<<speech "Aidra">>"Streamline. You're throwing water everywhere and going nowhere, which is the worst possible combination."<</speech>>
<<speech "$name">>"Right. Elbows in, head down, less splash."<</speech>>
<<speech "Aidra">>"Don't say understood. Say it and then do it, and I'll believe the first part."<</speech>>
He does it. It's marginally better and she doesn't comment, which from Aidra counts as a result.
Ariana is two lanes over and has been doing the same set since before anyone else arrived. Dark hair, dark eyes, nothing wasted in the stroke — she turns at the wall without surfacing properly and is gone again before the ripple reaches him.
Harley has a lane and is not really using it. She is bubbly in a way that survives even this room, and she has both arms folded on the lane rope watching Ariana go.
<<speech "Harley">>"She's been here since half six. I asked her once and she said she likes the pool empty, and I've thought about that a lot since."<</speech>>
<<speech "$name">>"You watch her a lot. You've been on that rope ten minutes."<</speech>>
<<speech "Harley">>"She's the best swimmer this school has had in years and nobody outside this room knows it. Somebody should be watching."<</speech>>
Ariana surfaces at the wall, pushes her goggles up, and looks at the pair of them with no expression at all.
<<speech "Ariana">>"I can hear all of it. The water carries."<</speech>>
<<speech "Harley">>"I was being nice about you!"<</speech>>
<<speech "Ariana">>"I know. You always are."<</speech>>
<<speech "$name">>"She talks about you when you're not in the room as well, for what it's worth."<</speech>>
She says it flatly, but she stays at the wall a moment longer than she needs to before she pushes off, and Harley beams at the water like she's been handed something.
<<speech "$name">>"That's me. I'll go first and get it over with."<</speech>>
<<speech "Aidra">>"Relay. All three. And somebody is going to push off that wall properly this time rather than stepping off it like they're getting out of a bath."<</speech>>
$name doesn't answer that one either. He gets into position and Harley pulls a face at him behind Aidra's back, and Ariana, who sees everything from the water, does not react at all.
<<elseif _tier is 2>>
The pool is doing what it always does — filter hum, the slap of water in the tile gutter, a kickboard bumping at the far end. The air above the surface has gone thick and sweet in a way chlorine cannot account for, and nobody has mentioned it, because none of them can hold a thought long enough to.
Aidra is still on the tile edge and has been trying to deliver the same instruction for a while.
<<speech "Aidra">>"Controlled inhale. Then — powerful exhale, and you —"<</speech>>
She stops. Her hand has gone to her own throat and then lower, and she is looking at the water rather than at anybody.
<<speech "$name">>"That's the third time you've started that sentence, Coach."<</speech>>
<<speech "Aidra">>"I'm aware. It keeps going."<</speech>>
She crouches at the pool edge in front of him and her knees come apart doing it and she doesn't adjust them, and when he puts a hand between her thighs through the suit she makes a noise that carries the whole length of the room.
The parasite is enjoying this. It has been quiet for weeks and now it is up close behind his eyes, delighted, appraising her like stock.
//Look at that. Thirty years of discipline and she's panting on the tile. Good bitch.//
Ariana has stopped mid-length. She is standing in the shallow end with the water at her ribs and both hands under the surface, and her face is doing something it has never done in this building.
<<speech "Ariana">>"I don't think about anything when I'm swimming. That's the entire point of swimming."<</speech>>
<<speech "$name">>"And now you can't get a single length in without stopping halfway."<</speech>>
<<speech "Ariana">>"No. Please come here. Please."<</speech>>
She says it twice more before he reaches her and does not appear to know she's doing it.
Harley has given up and is hanging off the lane rope with her forehead on her own arm, hips rolling against nothing.
<<speech "Harley">>"Is it just me? It feels like it's only me —"<</speech>>
<<speech "$name">>"Look at Ariana in the shallow end. Then tell me it's only you."<</speech>>
Harley looks. Ariana is standing in four feet of water with her eyes shut and her hand moving and her mouth open, and Harley makes a small wounded sound at the sight of it.
<<speech "Harley">>"Oh — oh, she never — she doesn't //do// that —"<</speech>>
<<speech "$name">>"She's doing it now. Let go of the rope, Harley."<</speech>>
//Three of them in a trough. Listen to it.//
<<elseif _tier is 3>>
The class is over and nobody has left. The lights on the far side are off because Aidra turned them off, which is the only decision she has managed to make in an hour.
Ariana gets out of the water first, which is the extraordinary part. The disciplined one, the one who wants nothing from anybody, hauling herself onto the tile dripping and going straight to her knees with her goggles still round her neck.
<<speech "Ariana">>"Please. I've been in that water two hours and it isn't helping —"<</speech>>
<<speech "$name">>"Then stop asking for it and take it. Open your mouth."<</speech>>
She does, and she is graceless about it, nothing like the way she swims, and the noise she makes around him has no words in it anywhere.
//She's been quiet her whole life and now listen. Nothing in there but an animal after all.//
Harley climbs out badly and shoves in beside her, and even now she is looking at Ariana as much as at him.
<<speech "Harley">>"I've never seen her want anything. Not once, not in three years —"<</speech>>
<<speech "$name">>"You're still watching her. Even now."<</speech>>
<<speech "Harley">>"I can't help it. Please, let me — please —"<</speech>>
Aidra comes last and comes down hardest. She kneels on the wet tile in her one-piece with her hair plastered to her neck, and this is a woman who has stood on this edge for a decade telling other people to try harder.
<<speech "Aidra">>"Don't make me say it."<</speech>>
<<speech "$name">>"Say it properly. You've made this whole class say worse."<</speech>>
<<speech "Aidra">>"Please. //Please.// There."<</speech>>
//Not nearly enough. Make the mare beg properly.//
<<speech "$name">>"Down on the tile with the other two."<</speech>>
The three of them work at him at the pool edge in a puddle of their own making, and the filter hums, and none of them is speaking in sentences any more.
<<else>>
Nobody books this pool now. The lane ropes are still strung and nobody swims in them and the tile at the shallow end is never dry.
They are on all fours when he comes in — Aidra, Ariana, Harley, in a row, dripping and open and already moving. There is nothing in any of their faces that could be called thought.
<<speech "Aidra">>"Please —"<</speech>>
<<speech "$name">>"That's the whole vocabulary now. One word, over and over, until I do something."<</speech>>
<<speech "Aidra">>"Please. Please. Please —"<</speech>>
//Three in a row in the wet, backs down, waiting. You could put a hand on any one of them.//
You take Aidra first, over the tile edge, and the woman who ran this room comes on the second stroke and keeps pushing back for more, and the sound echoes off the water and comes back doubled.
<<speech "Aidra">>"Breed me — I want it to take, I want to be too heavy to get in the water —"<</speech>>
<<speech "$name">>"You'd stand on that edge tomorrow with it running down your leg."<</speech>>
<<speech "Aidra">>"Yes. Do it."<</speech>>
Ariana doesn't ask, because Ariana has stopped being able to. She crawls sideways along the tile until she is under him and waits with her forehead down, shaking, and when he takes her she makes one long noise that does not stop until he does.
Harley is still trying to talk, which is the most Harley thing left in her — and she is still, even now, half turned towards Ariana.
<<speech "$name">>"Even now you're putting her in front of you."<</speech>>
<<speech "Harley">>"Her first — she should always go first — but me next, please, me next —"<</speech>>
<<speech "$name">>"You're the only one in here still using words. Head down."<</speech>>
//Good sow. She'll take it and thank you and be back in the water tomorrow asking again.//
Afterwards the three of them stay down on the wet tile, leaking into the puddle, breathing hard, waiting. Somewhere in the building a bell goes for a class none of them will attend.
<</if>>
<<case "Hallway_Gossip">>
<<if _tier is 0 or _tier is 1>>
<<speech "Violet">>"So, Marie and Blake have been together for a while now. But I heard—"<</speech>> Violet says, leaning in conspiratorially.
<<speech "Vanna">>"No. Stop. You're going to say something dramatic."<</speech>> Vanna interrupts, rolling her eyes.
<<speech "Violet">>"I'm just saying, I saw Blake and Myra in the hall together. They were whispering. It looked intense."<</speech>> Violet replies defensively.
<<speech "Maya">>"They're roommates. They probably needed to coordinate something about the dorm."<</speech>> Maya offers gently.
<<speech "Vanna">>(to $name) "You had a crush on Marie once, didn't you?"<</speech>> Vanna says, a smirk playing on her lips.
<<speech "$name">>"That was a long time ago."<</speech>> $name says, caught off guard.
<<speech "Violet">>"I knew it! There's history! This is getting interesting."<</speech>> Violet says delightedly.
<<speech "Maya">>"You seem happy for them, though. You don't seem bothered by it."<</speech>> Maya says gently.
<<speech "$name">>"I am. They're good together. Blake's good for her."<</speech>> $name replies honestly.
<<speech "Vanna">>"You're too nice about it. It's suspicious. Nobody's that nice about their old crush."<</speech>> Vanna says, studying him.
<<speech "Violet">>"He's hiding something. All the nicest people are hiding something."<</speech>> Violet adds.
<<speech "$name">>"I'm not hiding anything. Some people can just move on."<</speech>> $name says dryly.
<<speech "Violet">>"That's exactly what someone hiding something would say."<</speech>> Violet grins.
<<speech "Maya">>(laughing) "You're impossible, Violet."<</speech>> Maya shakes her head.
<<speech "Violet">>"I'm perceptive. There's a difference."<</speech>> Violet says with mock dignity.
<<elseif _tier is 2>>
The parasite stirs in $name’s chest, a warm, wet pulse that syncs with his heartbeat. The hallway feels different—the air thicker, the sounds of chatter and laughter taking on a honeyed edge. His friends aren’t just standing near him anymore. They’re leaning in. Their eyes linger too long. Their breaths come a little faster.
Violet’s blouse is unbuttoned one too many, the lace trim of her bra peeking out. Vanna’s skirt has ridden up, the fabric clinging to the curve of her ass when she shifts. Maya’s sweater hugs her body like a second skin, her fingers twitching at her sides like she’s fighting the urge to touch herself.
<<speech "Violet">>"Okay, so—Marie and Blake—"<</speech>> Violet starts, but her voice is softer now, her usual sharpness dulled by something warmer. She licks her lips, her gaze flicking to $name’s mouth before she forces herself to focus. <<speech "Violet">>"I saw Blake and Myra in the hall again. They were close. Like, really close."<</speech>> Her fingers tap against her collarbone, her nails digging in just enough to leave faint red marks.
<<speech "Vanna">>"No. Stop."<</speech>> Vanna says, but her protest lacks its usual bite. She shifts, her thighs pressing together, a faint flush creeping up her neck. <<speech "Vanna">>"You always jump to the worst conclusions."<</speech>> Her voice is huskier than usual.
<<speech "Maya">>"Maybe they were just—"<</speech>> Maya starts, but her words trail off as $name moves—just a slight shift, his shoulder brushing against hers. She shivers, her nipples hardening under her sweater. <<speech "Maya">>"I-I mean, they could’ve been talking about anything…"<</speech>> Her fingers twist in the fabric of her skirt.
Vanna’s gaze flicks to $name, her smirk slower, heavier. <<speech "Vanna">>"$name, you are our expert on the Marie-Blake situation"<</speech>> Her tongue darts out, wetting her lower lip. <<speech "Vanna">>"I bet you noticed things. About how they act together."<</speech>>
The parasite purrs. $name’s fingers twitch. <<speech "$name">>"It was a long time ago,"<</speech>> he says, but his voice is deeper, rougher. His hand drifts to Violet’s waist, his thumb brushing the bare skin above her skirt. She gasps, her back arching slightly.
<<speech "Violet">>"I knew it—"<</speech>> Violet breathes, but her train of thought derails as his fingers squeeze. <<speech "Violet">>"Y-You’re hiding something…"<</speech>> Her words dissolve into a whimper.
<<speech "Maya">>"You don’t seem… bothered…"<</speech>> Maya whispers, her voice trembling. She presses her thighs together, her breath hitching as $name’s free hand finds her hip, his touch burning through the fabric.
<<speech "$name">>"I’m not."<</speech>> His fingers tighten. <<speech "$name">>"But I do know things."<</speech>> His lips curl. About what they like. About how they’d sound if I bent them over right here.
Vanna’s breath catches. <<speech "Vanna">>"You’re different today,"<</speech>> she murmurs, her voice thick. <<speech "Vanna">>"Something’s… changed."<</speech>> Her hand drifts to his chest, her fingers splaying over his heartbeat—too fast, too strong.
<<speech "Violet">>"Y-Yes…"<</speech>> Violet agrees, her voice breathy. <<speech "Violet">>"You’re hiding something. But I don’t… I don’t care anymore…"<</speech>> Her head tilts back as his hand slides higher, his thumb grazing the underside of her breast.
Maya lets out a soft, needy sound. <<speech "Maya">>"N-$name…"<</speech>>
The parasite whispers: They’re yours. Take them.
<<elseif _tier is 3>>
The hallway is empty—or at least, it should be. The parasite has seen to that, twisting perceptions, bending reality just enough to give them privacy. The fluorescent lights flicker, casting long shadows that make the lockers look like bars of a cage.
Violet’s blouse is open, her bra pushed up to frame her breasts, her skirt hitched high enough to show off her lace panties—already damp. Vanna’s leather jacket is pooled on the floor, her tank top clinging to her sweat-slicked skin, her nipples piercing through the thin fabric. Maya’s sweater is gone, her bra unclasped, her hands trembling as she cups her own tits, her thighs pressed tight together.
$name owns them now. The parasite has seen to that.
<<speech "Violet">>"N-$name…"<</speech>> Violet whimpers, her back against the lockers, her fingers fumbling with her bra. <<speech "Violet">>"I-I was just talking about that new couple, but I—I can’t remember why it mattered…"<</speech>> Her knees buckle as he steps closer, his hand tangling in her hair.
<<speech "Vanna">>"Fuck the gossip,"<</speech>> Vanna growls, her voice rough. She drops to her knees in front of him, her hands going straight for his belt. <<speech "Vanna">>"I want to know what you’ve been hiding."<</speech>> Her fingers tremble as she frees his cock, her breath hitching at the sight of it—thick, veined, already leaking.
<<speech "Maya">>"P-Please…"<</speech>> Maya whispers, her hands covering her mouth as she watches Vanna’s tongue dart out, swirling over the tip. <<speech "Maya">>"I-I don’t understand why this feels so… good…"<</speech>> Her fingers slip between her thighs, rubbing frantically over her panties.
$name doesn’t answer. He doesn’t need to.
Vanna takes him into her mouth with a moan, her lips stretching around his girth, her throat fluttering as she takes him deeper. Violet whines, crawling to his other side, her hands joining Vanna’s, their fingers intertwining as they stroke the base of his cock.
<<speech "Violet">>"M-Maya, help us…"<</speech>> Violet gasps, her free hand groping at her own breast. <<speech "Violet">>"He tastes so good…"<</speech>>
Maya breaks. She scrambles forward, pressing her face into the crook of his thigh, her tongue dragging up the underside of his shaft before she joins Vanna, their mouths working in tandem—licking, sucking, worshipping.
<<speech "Maya">>"I-I never… I didn’t want this before…"<</speech>> Maya sobs around his cock, her words vibrating against his skin. <<speech "Maya">>"But now I need it…"<</speech>>
Vanna pulls back just long enough to pant, <<speech "Vanna">>"Fuck, you’re huge…"<</speech>> before diving back in, her cheeks hollowing as she takes him to the root. Violet’s fingers dig into his ass, her nails scoring through the fabric of his pants as she begs:
<<speech "Violet">>"C-Come in our mouths, $name… Please…"<</speech>>
The parasite thrums in approval. Good. Make them choke on you.
<<else>>
The hallway isn’t a hallway anymore. It’s a breeding ground, the walls slick with condensation, the air thick with the scent of sex and submission. The parasite has rewritten them—mind, body, soul.
Violet is naked, her body glistening with sweat, her thighs spread wide as she fingers herself, her cunt dripping onto the floor. Vanna is on all fours, her ass in the air, her mouth still stretched around his cock, her eyes glazed with devotion. Maya is pressed against the lockers, her legs trembling, her pussy clenching around nothing as she whines, her tits heavy and swollen.
<<speech "Violet">>"I-I used to talk so much…"<</speech>> Violet giggles, her voice slurred. <<speech "Violet">>"Now I just… want…"<</speech>> Her fingers work furiously between her legs, her other hand groping at her own breast. <<speech "Violet">>"I want you to fuck me until I break."<</speech>>
Vanna gags around his cock, but she doesn’t pull away. She deepthroats him, her nose pressing into his skin, her throat milking him. <<speech "Vanna">>"Mmmf—all those whores…"<</speech>> she moans, pulling back just enough to speak. <<speech "Vanna">>"Stealing… what is mine…"<</speech>> Her hand drifts back, her fingers teasing her own soaked pussy.
<<speech "Maya">>"P-Please, $name…"<</speech>> Maya sobs, her body trembling. <<speech "Maya">>"I-I can’t think anymore… Just use me…"<</speech>> She spreads her legs wider, her fingers stretching her own cunt open in offering.
$name grins—or rather, the parasite grins through him.
He slams into Vanna’s mouth first, fucking her throat with rough, deep strokes. Violet crawls forward, her tongue joining Maya’s as they lick and suck at his balls, their hands roaming over each other’s bodies. The parasite sings in his veins, its voice a slick, wet whisper:
Breed them. Ruin them. Make them yours.
<<speech "Vanna">>"Yes—! Fuck—! I’m yours—!"<</speech>> Vanna gurgles around his cock, her throat convulsing as he unloads down it, her body shuddering as she comes from the taste alone.
Violet and Maya scream in unison, their bodies writhing as the parasite’s influence detonates inside them, their minds shattering under the weight of their orgasms.
<<speech "Violet">>"M-More… Please…"<</speech>> Violet sobs, her cunt gushing as she collapses onto the floor.
<<speech "Maya">>"I-I love you…"<</speech>> Maya whimpers, her words slurred, her eyes empty of everything but devotion.
The parasite purrs.
Good. Now fill them all.
<</if>>
<<case "Rooftop_Standard">>
<<if _tier is 0 or _tier is 1>>
The roof of the school is open at lunch and half the sixth form comes up. There are benches along the east side, a low wall you can sit on if you don't mind the wind, and a permanent argument about whether the door should be propped. On a decent day there are twenty people up here eating out of tupperware.
Kailey has the good corner, which she gets by arriving early and refusing to move. She is a close friend of $name's, all warmth and gossip and an open, teeth-showing smile, and she is leaning on the railing looking out over a town she could describe building by building.
<<speech "Kailey">>"That's the arcade, that's the back of the mall, and that's Mrs Ellery's roof, and she has had a man up on it twice this term."<</speech>>
<<speech "$name">>"You've been keeping an eye on Mrs Ellery's roof. Deliberately."<</speech>>
<<speech "Kailey">>"I keep an eye on everything. It's a hobby and it costs nothing."<</speech>>
<<speech "$name">>"Remind me never to have a man on my roof."<</speech>>
Chloe is on the low wall with her lunch on her knees, blonde and small and one of the easiest people in the school to be around. She follows the rules, mostly, and questions them when they seem wrong.
<<speech "Chloe">>"Can you say all that a bit quieter. There are actual people up here."<</speech>>
<<speech "Kailey">>"Nobody's listening."<</speech>>
<<speech "Chloe">>"Two of them are listening. One of them has stopped eating."<</speech>>
Scarlet is lying flat on her back on the concrete with her arms out, red hair everywhere, apparently studying the sky. She is $name's roommate and she is curious in a way that gets her into trouble, because she asks the question everybody else has agreed not to.
<<speech "Scarlet">>"So what's actually going on with you? Not the version you give people."<</speech>>
<<speech "$name">>"There's a version I give people? You've worked out I have a version."<</speech>>
<<speech "Scarlet">>"There's absolutely a version. It's a good version. I'd just like the other one."<</speech>>
<<speech "Kailey">>"Scarlet, you live with him. You know more than any of us do."<</speech>>
<<speech "Scarlet">>"I know what time he comes in. That isn't the same as knowing anything."<</speech>>
<<speech "Chloe">>(mildly, over her sandwich) "That is a slightly unsettling thing to have noticed."<</speech>>
<<speech "Scarlet">>"Is it? I notice everything about everyone. Nobody's ever minded before."<</speech>>
<<speech "$name">>"Nobody's ever told you they minded. That isn't quite the same."<</speech>>
Kailey laughs hard enough to have to hold the railing. Two benches along, someone's crisp packet goes over the edge and there is a brief communal noise about it.
<<elseif _tier is 2>>
The roof is busy. It's a decent day, so there are people on both benches and a group sitting on the concrete near the stairwell door. The air up here should be moving and it isn't quite — there's a weight to it, close and sweet, and it has been building since he came up.
Kailey hasn't moved from the railing. Her skirt is doing less than it was and she has made no attempt to fix it, and when $name comes up behind her and slides a hand underneath she leans back into his chest and carries straight on.
<<speech "Kailey">>"— and the woman from the flower shop's been going in there Thursdays, which everyone has noticed and nobody will say."<</speech>>
<<speech "$name">>"So you're not going to mention this either. Any of it."<</speech>>
<<speech "Kailey">>"Mention what? I'm telling you about the flower shop."<</speech>>
She rocks back against his hand and doesn't lose the thread. Below them in the yard two teachers cross from one building to the other without looking up.
Chloe is on the low wall with her lunch still on her knees and her legs apart, and she is watching all of this with an expression of mild social concern.
<<speech "Chloe">>"People can see you from the benches."<</speech>>
<<speech "$name">>"That's the objection you're going with. Out of everything happening here."<</speech>>
<<speech "Chloe">>"It's the one I've got. I'd rather not be talked about."<</speech>>
She lets him push her knees wider without a flicker and goes back to her sandwich.
Scarlet is not managing any of this. She was on her feet and now she isn't, sitting down hard on the concrete with her back against the vent housing, and her breathing has gone wrong.
<<speech "Scarlet">>"Something's happening to me. It's been happening since this morning and it's getting worse —"<</speech>>
<<speech "$name">>"Then say what you want. Out loud, in words."<</speech>>
<<speech "Scarlet">>"I don't //know// what I want, that's what's wrong with it —"<</speech>>
She has her hand between her legs before she finishes the sentence and looks genuinely shocked to find it there.
The parasite stirs, interested, and looks at her the way you look at something in a pen.
//That one's already gone. Nothing left in her but heat. Let her whine.//
<<speech "Scarlet">>"Please —"<</speech>>
<<speech "Kailey">>(over her shoulder, mildly) "She's been like that all day. I did wonder."<</speech>>
<<speech "Chloe">>"Should somebody do something?"<</speech>>
<<speech "$name">>"She's past being helped. Look at the state of her against that vent."<</speech>>
Two benches away a group carries on with their lunch.
<<elseif _tier is 3>>
The roof is quieter at this hour but it is not empty. There are people on the far bench and the stairwell door is propped, and nobody involved in this has suggested doing anything about either.
Scarlet does not last. She is on her knees before he's fully across the concrete, and there is nothing curious or bright about her any more, and she is not asking questions.
<<speech "Scarlet">>"Please. Please, I've been up here all lunch waiting —"<</speech>>
<<speech "$name">>"You've stopped forming sentences. You had nothing but questions this morning."<</speech>>
<<speech "Scarlet">>"I don't — please —"<</speech>>
//That's all that's left in there. She'll take it now and take it again in an hour. Good little bitch.//
She makes a noise around him with nothing human in it, and doesn't stop, and her hand doesn't leave herself once.
Kailey comes over and kneels down beside her at her own pace, entirely unbothered.
<<speech "Kailey">>"Shove up. You've had him for ages."<</speech>>
<<speech "$name">>"She can't hear you. She stopped hearing anything a while ago."<</speech>>
<<speech "Kailey">>"No, she's gone. She does go."<</speech>>
She takes over the way you'd take a turn at something at a fair, and carries on talking between.
<<speech "Kailey">>"Flower shop woman was there again, by the way. Thursday, like clockwork."<</speech>>
<<speech "$name">>"You are giving me local gossip with your mouth full."<</speech>>
Chloe kneels last, tucks her skirt under her knees so it doesn't drag on the concrete, and gets on with it with the same mild competence she brings to a group project.
<<speech "Chloe">>"For the record, people on that bench can definitely see us."<</speech>>
<<speech "$name">>"Noted. Both of you keep going."<</speech>>
Beside them Scarlet has started making a low continuous sound and does not appear to know she is doing it.
<<else>>
The roof still fills up at lunch. People still eat on the benches. Nobody comes to this end any more, and nobody has ever explained why to anybody.
Kailey is bent over the railing with her skirt gone, waiting, chatting. Chloe is sitting on the low wall with her legs open and her bag squared neatly beside her. Scarlet is on all fours on the concrete and has been for a while.
<<speech "Kailey">>"Whenever you like. I've got a free and then art, and art doesn't matter."<</speech>>
<<speech "$name">>"You'll walk into art like this and sit down next to people you know."<</speech>>
<<speech "Kailey">>"I'll walk into art like this and tell them about the flower shop woman. Fill me first."<</speech>>
You take her over the railing above a yard with people crossing it and she moans steadily into the wind, eyes on the town the whole time.
<<speech "Kailey">>"That's it — breed me — I want to sit in art dripping and say nothing —"<</speech>>
Chloe takes her turn on the low wall, knees up, and lodges her objection one final time while it's happening.
<<speech "Chloe">>"They can still see us from the benches. Fill me up anyway."<</speech>>
<<speech "$name">>"Noted for the record. Hold the wall."<</speech>>
Scarlet hasn't moved from where she is and hasn't spoken in some time. When he gets to her she pushes back before he's touched her, and the sound out of her is not a word.
//Face down on a roof, arse up, waiting. Nothing in there at all now. Breed the animal.//
<<speech "$name">>"Say something. Anything."<</speech>>
<<speech "Scarlet">>"…Please —"<</speech>>
<<speech "$name">>"That's not a word any more. That's a noise you make."<</speech>>
She comes on the second stroke and keeps pushing back for more, and afterwards stays exactly where she is on the concrete, leaking, waiting, while Kailey redoes her hair in a phone camera and Chloe brushes grit off her skirt.
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<set $sceneColor = "#44aaff">>
<<set $sceneLabel = "City · Nightlife">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "Club_Standard">>
<<if _tier is 0 or _tier is 1>>
The club pulses with bass and colored lights, bodies moving on the dance floor like a single organism. $name sits at the bar, nursing a drink, the parasite dormant but present. He knows these women from lots of nights like this—Lexi behind the bar, Leda in the DJ booth, Avery somewhere in the crowd.
Lexi wipes down the counter in front of him, her light brown hair pulled back in a practical ponytail, her warm brown eyes scanning the crowd with practiced awareness. She wears her usual bartender uniform: a fitted black tank top under a flannel shirt, jeans that allow her to move, comfortable sneakers. The tattoos on her forearms peek out as she works.
<<speech "Lexi">>"You look like you're contemplating the meaning of life, $name. Or just avoiding your homework."<</speech>> She smirks, the expression sharp and knowing. <<speech "Lexi">>"The usual?"<</speech>>
<<speech "$name">>"Just water tonight, Lexi."<</speech>>
<<speech "Lexi">>(raising an eyebrow) "Designated driver or just boring?"<</speech>> She's teasing, her tone playful but protective. <<speech "Lexi">>"Don't tell me you're still pining over that girl from your lit class."<</speech>>
<<speech "$name">>"I have a girlfriend now, Lex. You know that."<</speech>>
<<speech "Lexi">>(grinning) "I know. I'm just checking if you're treating her right. I'll kick your ass if you're not."<</speech>>
Leda leans over from the DJ booth, her jet-black hair falling around her face, bright blue eyes catching the strobe lights. She's in her typical gear: a cropped band tee showing her tattooed midriff, ripped jeans that show more skin than they cover, combat boots. Headphones rest around her neck like a permanent accessory.
<<speech "Leda">>(shouting over the music) "$name! Tell your $family I saved her favorite song for last call!"<</speech>> She grins, infectious energy radiating off her. <<speech "Leda">>"And tell her she owes me a drink for that favor!"<</speech>>
<<speech "$name">>(smiling) "I'll pass it along. I'm sure she can feel it from her bed."<</speech>>
<<speech "Leda">>"You better! Or I'll start playing polka music when you're here!"<</speech>> She laughs, already turning back to her decks, her body moving with the rhythm she's creating.
Avery appears from the crowd, petite and magnetic, her black hair catching the blue lights. She wears a sequined top that catches every flash, fitted jeans, heels that add inches to her 4'11" frame. She's been dancing; her skin glows with sweat, her smile dazzling and seeking.
<<speech "Avery">>"There you are!"<</speech>> She slides onto the stool next to $name, her shoulder pressing against his. <<speech "Avery">>"I've been looking for you for twenty minutes. Dance with me."<</speech>> It's not quite a question, but not quite a demand either—her flirtatious nature wrapping around genuine desire for connection.
<<speech "$name">>"I'm not really dancing tonight, Avery."<</speech>>
<<speech "Avery">>(pouting, but her eyes are kind) "You're never dancing. One song. Come on."<</speech>> She takes his hand, her fingers small but insistent. <<speech "Avery">>"I promise I won't step on your feet. Much."<</speech>>
<<speech "Lexi">>(watching, amused) "Go on, $name. I'll watch your water. It might get wild while you're gone."<</speech>> Her dry wit cuts through the noise.
<<speech "Leda">>(over the speakers) "This one's for the wallflowers! Time to bloom!"<</speech>> She catches $name's eye from the booth, winks, and drops a track that's impossible not to move to.
Avery pulls $name onto the floor. He moves stiffly at first, but she laughs, spinning herself under his arm, her sequined top flashing. <<speech "Avery">>"See? Not so hard!"<</speech>>
Leda waves from the booth, giving him a thumbs up. Lexi watches from behind the bar, shaking her head with a smile. It's a normal night. Friends, acquaintances, the comfortable space of a club where everyone knows your name but not all your secrets.
<<elseif _tier is 2>>
The club's ventilation carries something new—thick, musky, irresistible. $name sits at the bar, and the pheromones pour off him in waves, invisible but overwhelming. The parasite has awakened.
Lexi leans over the bar, her tank top suddenly too tight, the flannel shirt she's wearing over it unbuttoned to reveal the sheer fabric beneath. Her jeans are the same, but she's rolled them up higher, and she keeps bending over to reach for bottles, her ass presented to $name.
<<speech "Lexi">>(breathless, wiping the same spot on the counter) "Is it... is it hot in here?"<</speech>> She fans herself, the motion making her breasts strain against the tank top. <<speech "Lexi">>"I feel... dizzy."<</speech>>
<<speech "$name">>(voice deeper, commanding) "You should unbutton more. Cool off."<</speech>>
<<speech "Lexi">>(nodding, her fingers moving to her flannel) "Yeah... good idea..."<</speech>> She unbuttons further, the sheer tank showing everything, her nipples hard and visible. <<speech "Lexi">>"You smell really good tonight. What is that?"<</speech>>
Leda stumbles down from the DJ booth, her cropped tee riding up, her ripped jeans showing more skin than before. She's barefoot, having abandoned her boots, her blue eyes glassy and fixed on $name.
<<speech "Leda">>(grabbing $name's shoulder) "Hey. Something's... something's weird."<</speech>> She sways to music that's not playing. <<speech "Leda">>"I can't stop looking at you. Is that weird? Jewelz would kill me."<</speech>>
<<speech "$name">>"It's not weird. Touch me if you want."<</speech>>
<<speech "Leda">>(whimpering, her hand sliding to his chest) "I do. I really do."<</speech>>
Avery appears, her sequined top shorter than before, her jeans unbuttoned at the top, her heels making her wobble.
<<speech "Avery">>(breathless, sliding next to him) "There you are. I've been... thinking about you."<</speech>> She presses against his side. <<speech "Avery">>"I know you have a girlfriend. But I can't stop wanting..."<</speech>>
<<speech "Lexi">>(watching, her hand between her legs under the bar) "Avery... you feel it too?"<</speech>>
<<speech "Avery">>(nodding, desperate) "It's him. It's $name. He smells like... like everything."<</speech>>
<<speech "$name">>(standing, commanding) "VIP room. Now. All of you."<</speech>>
They follow without question. The VIP room is small, a roped-off corner with plush seating, dimmer than the main floor. The door curtain falls closed and the pheromones concentrate.
<<speech "Lexi">>(immediately, her hands on his belt) "I know I should stop. But I can't."<</speech>> She's on her knees, her flannel shirt falling off her shoulders, her tank top showing her hard nipples.
<<speech "Leda">>(beside her, her hands on his zipper) "I don't care about should. I care about now."<</speech>> She pulls his cock free through his pants, her eyes widening. <<speech "Leda">>"Fuck."<</speech>>
<<speech "Avery">>(small hands joining theirs, stroking him) "I've wanted you for months."<</speech>> Her sequined top pushed up, her jeans shoved down to her knees.
They work him together with their hands—three women stroking, squeezing, exploring. Lexi's bartender hands are skilled and firm. Leda's DJ fingers are creative, teasing. Avery's small hands are eager, desperate.
He comes with a groan, spilling over their hands. They fight to catch it, to rub it into their skin, their depraved clothing soaked.
<<speech "Lexi">>(licking her fingers) "More. I need more."<</speech>>
<<speech "Leda">>(grinning, wild) "Fuck the set. I only want this."<</speech>>
<<speech "Avery">>(crying, smiling) "This is real. Finally real."<</speech>>
<<speech "$name">>(commanding) "Lexi, bend over the couch. Leda, finger her. Avery, kiss me. Now."<</speech>>
Lexi bends over the plush VIP couch, her flannel shirt falling away, her tank top pushed up, her jeans framing her ass. Leda kneels behind her, her tattooed fingers sliding into Lexi without hesitation, her other hand between her own legs. Avery straddles $name's lap, her small body pressed against him, her mouth finding his in a desperate, open-mouthed kiss.
<<speech "Avery">>(kissing him desperately, her hand stroking him again) "I've flirted with a hundred guys... none of them made me feel like this..."<</speech>>
They work each other and him, hands moving, mouths connected, the VIP room filled with wet sounds and gasps. Lexi comes first, screaming into the couch cushions, Leda's fingers driving her over the edge. Leda follows, rubbing herself against Lexi's thigh, her tattooed body convulsing. Avery comes last, grinding against $name's hand, her sequined top scratching his palm, her kiss never breaking.
<<speech "Lexi">>(panting, her sharp wit reduced to whispers) "Again... please... my break is almost over..."<</speech>>
<<speech "Leda">>(laughing, wild) "Fuck breaks. Fuck everything. Only this."<</speech>>
<<elseif _tier is 3>>
The VIP room of the Club has become their world, the curtain closed, the music outside a distant thrum. $name sits on the plush couch like a throne, the pheromones thick enough to taste. The girls orbit him, desperate, their clothing transformed into lewd framing devices.
Lexi wears her tank top pulled down to expose her breasts, the flannel shirt tied beneath them like a shelf. Her jeans are unbuttoned, the zipper down, showing her lack of underwear.
Leda has her cropped tee tied around her neck and breasts, leaving her tattooed back bare, her ripped jeans rolled down to expose everything.
Avery wears her sequined top as a makeshift bra—pushed up, barely containing her, her jeans cut into shorts so short they're just fabric strips.
<<speech "Lexi">>(kneeling, her sharp eyes desperate) "Master... I called you that in my head. Is that okay?"<</speech>>
<<speech "$name">>"Yes. Say it again."<</speech>>
<<speech "Leda">>(grinding against the couch arm, her pussy leaving a wet spot) "Jewelz would hate this. But I don't care. I've never cared about rules."<</speech>> She spreads herself. <<speech "Leda">>"Command me, Master. Your rebellious little slut."<</speech>>
<<speech "Avery">>(her face buried in $name's lap, her voice muffled) "I've flirted with a hundred guys. None of them made me feel like this. Connected. Owned."<</speech>> She pulls his cock free, her small hands stroking him, her mouth watering. <<speech "Avery">>"Please let me suck you, Master. Please let me show you I'm more than just a flirt."<</speech>>
<<speech "$name">>"All of you. Mouths on me. Now."<</speech>>
They obey instantly. Avery takes him first, her mouth stretching around him, her sequined top catching the light as she bobs. Lexi licks the base, her tongue hot and desperate. Leda sucks his balls, her tattooed fingers stroking what Avery can't take.
<<speech "Avery">>(muffled, slurping) "I want to taste you. Want to swallow you."<</speech>>
<<speech "Lexi">>(pulling back, gasping) "I've protected this bar from creeps for years. Now I want to be used by you."<</speech>> She takes him from Avery, her mouth hot and skilled, her tongue piercing clicking against his shaft.
<<speech "Leda">>(sucking harder, her voice vibrating) "Make me your DJ slut. Your $family's friend whore."<</speech>>
He comes with a roar, filling Avery's mouth first—she swallows desperately—then Lexi takes the next pulse, her eyes rolling back—then Leda catches the last on her face, rubbing it into her tattoos.
<<speech "Avery">>(breathless, her face glazed) "More. Please. I need your cum inside me."<</speech>>
<<speech "Lexi">>(stroking him, keeping him hard) "Fill me, Master. Make me serve drinks with your cum deep in my stomach."<</speech>>
<<speech "Leda">>(grinning, cum on her face) "Fuck the set. I only want to hear you moaning while you use us."<</speech>>
<<else>>
The VIP room has become a temple of submission, the curtain never opening, the outside world forgotten. $name sits on the couch, fully the host, his eyes black with the parasite's hunger. The girls exist to serve him, their clothing depraved versions of their former selves.
Lexi wears her bartender tank top cut into a crop top that ends just below her breasts, the fabric stretched tight. Her flannel shirt is tied around her waist like an apron—beneath it, she's naked. Her jeans are gone, her tattoos fully visible.
Leda wears her cropped tee as a choker and nothing else, her ripped jeans rolled down to her knees, her tattooed body completely bare above.
Avery wears her sequined top tied around her hips like a belt, framing her pussy, her small breasts marked with handprints and cum, her heels still on.
<<speech "$name">>"Lexi, prepare the others. Leda, present your ass. Avery, your mouth belongs to me. Now."<</speech>>
They obey without hesitation. Lexi immediately moves to position Leda on her hands and knees, her tattooed ass in the air, her ripped jeans around her knees. Lexi spreads her, shows $name everything. Avery positions herself between his legs, her mouth open.
<<speech "Lexi">>(her voice sharp even in submission) "She's ready, Master. Wet and open. Like me. Like all of us."<</speech>>
<<speech "Leda">>(moaning) "Please! I've been wild my whole life! Now I want to be owned! I'm your whore! Your rebellious breeding slut!"<</speech>>
<<speech "Avery">>(muffled, her mouth full of him) "Mmmph! Mmm!"<</speech>>
He takes Leda first, grabbing her hips, slamming into her in one brutal thrust. Lexi holds her down, while Avery continues sucking, her rhythm matching his thrusts.
<<speech "Leda">>(screaming) "Yes! Harder! Breed me! Make me your breeding vessel!"<</speech>>
He fills her, flooding her womb. She collapses, laughing and crying. Lexi immediately takes her place.
<<speech "Lexi">>(looking back) "I've protected this space for years. Now I want you to invade it. Invade me. Your bartender whore."<</speech>>
He takes her roughly, her wit reduced to begging screams. She comes hard, and he fills her too.
Avery last, her small body flipped onto her back, her sequined belt the only thing she's wearing, her heels in the air.
<<speech "Avery">>(whimpering) "Master. I've been looking for this my whole life. Being owned. Being yours."<</speech>> She wraps her legs around him as he enters her. <<speech "Avery">>"Your petite whore. Finally real."<</speech>>
He breeds her last, filling her with everything he has. They collapse around him, a tangle of tattooed limbs and depraved clothing.
<<speech "Lexi">>(whispering) "Master... will you use me again before my shift?"<</speech>>
<<speech "Leda">>(laughing) "Fuck the club. I'll play music here. Only for you."<</speech>>
<<speech "Avery">>(cuddled against him) "I don't need to flirt anymore. I just need to serve you. Forever."<</speech>>
<</if>>
<<case "Club_Night">>
<<if _tier is 0 or _tier is 1>>
None of this was planned. Maya said on Tuesday that she wanted to go dancing, Claire overheard it from the other end of the corridor and invited herself within about four seconds, and then Claire came and got you.
<<speech "Claire">>"You're coming."<</speech>>
<<speech "$name">>"I've got things on."<</speech>>
<<speech "Claire">>(already holding your coat) "You've got //brooding// on. That's not a thing, that's a hobby, and you've been doing it in a stairwell since Monday."<</speech>>
So: a club on a Friday, four people who have never been out together, and a booth Maya secured by arriving forty minutes early because Maya is the only one of you who follows through on anything.
The place smells of spilled sugar and warm bodies and whatever they put in the fog machine at eleven. The music is loud enough that everything is said twice.
Maya is delighted about all of it. Dark hair, a smile that does not switch off, a genuine talent for making four strangers feel like a group — she has already got everyone a drink and learned the barman's name.
<<speech "Maya">>"Right. Caitlyn — that one. By the pillar. Blue shirt."<</speech>>
Caitlyn is the fourth, and she is here because Maya has decided she needs to be. She works the desk at the hotel, finishes at eleven most nights, and has the specific posture of somebody who has spent four years being pleasant to strangers professionally. Blonde, tired, in a top she has clearly borrowed.
<<speech "Caitlyn">>(without turning round) "No."<</speech>>
<<speech "Maya">>"You haven't looked."<</speech>>
<<speech "Caitlyn">>"I don't need to look. I'm not going to find a nice guy in a nightclub — at most a handsome one, Maya."<</speech>>
<<speech "Claire">>(delighted) "Oh, she's //good//."<</speech>>
<<speech "$name">>"She's been here twenty minutes and she's already worked out the whole room."<</speech>>
<<speech "Caitlyn">>"It's not difficult. It's the same forty men in a different order every Friday."<</speech>>
<<speech "Maya">>"That's a terrible attitude and you've had it since we got here."<</speech>>
<<speech "Caitlyn">>"I've had it since I was nineteen. It's load-bearing."<</speech>>
Claire props her chin on her hand and studies Caitlyn with open interest — this is the first time they have met, and Claire has clearly decided she is worth keeping.
<<speech "Claire">>"What's wrong with the blue shirt?"<</speech>>
<<speech "Caitlyn">>"He's checked his reflection twice in four minutes and once in a pint glass."<</speech>>
<<speech "Maya">>"That's observant, not a flaw."<</speech>>
<<speech "Caitlyn">>"I check people in for a living. Everything's a flaw."<</speech>>
<<speech "$name">>"How long did I take?"<</speech>>
<<speech "Caitlyn">>(a beat, appraising) "You looked at the exits when you came in and you've had your back to the wall all night. So — bad night, or a bad habit."<</speech>>
<<speech "Claire">>"//Brooding//, is what it is. I've been saying."<</speech>>
<<speech "$name">>"I don't brood. I have a resting face and a stairwell I like."<</speech>>
<<speech "Maya">>"Leave him alone. He came, didn't he?"<</speech>>
<<speech "Claire">>"He came because I held his coat hostage."<</speech>>
<<speech "$name">>"That is a completely accurate account of how I got here."<</speech>>
Maya spends the next hour attempting three more introductions on Caitlyn's behalf, all of which fail on technical grounds inside twenty seconds, and by the fourth one Caitlyn has started supplying the objections before Maya finishes pointing.
Nobody dances. Everybody says they will. The four of you stay in the booth until half one, and at some point during it the evening stops being four people who don't know each other.
<<elseif _tier is 2>>
The booth has become a standing thing. Nobody arranged it—it simply happens on Fridays, the same booth somehow always free, the air in the corner warm and thick with sweetness that pools like fog. The group standing nearest keep drifting further away without deciding to, their eyes sliding off your table.
Maya's legs are across your lap, which started three weeks ago as a joke about space and has quietly stopped being one. Her skirt has ridden up, showing her thighs, and she doesn't adjust it. Her smile is warmer, aimed at you now rather than the room.
<<speech "Maya">>(close, over the music, her hand on your chest) "This alright?"<</speech>>
<<speech "$name">>"You've had your legs on me for an hour."<</speech>>
<<speech "Maya">>"That's not what I asked."<</speech>>
<<speech "$name">>"It's alright, Maya. It's been alright for about a month."<</speech>>
<<speech "Maya">>(pleased, confused by her own face) "Good. I wasn't going to move either way."<</speech>>
Claire's jacket is gone, her top unbuttoned to show her bra, if she had one, her skirt hiked as she studies your face. She runs her experiment with larger increments now: hand on your thigh, then your hip, then her fingers brushing your cock through your jeans under the table.
<<speech "Claire">>(watching your face, her fingers pressing) "Tell me to move."<</speech>>
<<speech "$name">>"No."<</speech>>
<<speech "Claire">>"//Interesting.//"<</speech>> She doesn't move her hand. She strokes you through the denim, her testing nature turned to desperate need to see you break.
Caitlyn has stopped watching the room. Her borrowed top is stretched tight, her skirt riding up as she shifts, her professional observation turned to fixation on you. She has one hand under the table, between her legs, pressing through her skirt.
<<speech "Caitlyn">>(her voice hoarse) "I've worked out I don't come here for the club. I don't even //like// the club."<</speech>>
<<speech "$name">>"Then what?"<</speech>>
<<speech "Caitlyn">>(not looking up, her hand moving) "…Don't make me say it in a booth."<</speech>>
She moves round to your other side, pressing against you, Maya's legs still across your lap, Claire's hand on your cock, the four of you surrounded by music and bodies and the sweet thick air of corruption.
<<elseif _tier is 3>>
Friday, half eleven, the club heaving, the booth at the back somehow still yours. The air is thick with pheromones, sweet and musky, fogging the mirrors. People walk past, eyes sliding off, the nearest groups drifting away without knowing why.
Claire has your cock out under the table, her skirt hiked to her waist, her fingers slick as she strokes you. Her experiments are no longer small.
<<speech "Claire">>(against your ear, her hand working) "Tell me to stop."<</speech>>
<<speech "$name">>"You've been saying that for two months and you've never once meant it."<</speech>>
<<speech "Claire">>"And you've never once said it."<</speech>>
<<speech "$name">>"I'm not going to. Get on with it."<</speech>>
<<speech "Claire">>"//God.//"<</speech>>
She slides under the table, onto the sticky floor, her mouth finding you, her testing nature reduced to pure cocksucking. A man leans on the end of the booth, shouting over the music, and doesn't look down.
Maya is beside you, her skirt gone, her panties pushed aside, her fingers inside herself as she watches. The warmth hasn't left her smile—it's simply been aimed, focused, desperate.
<<speech "Maya">>"Share."<</speech>>
<<speech "Claire">>(muffled, pulling back with spit on her chin) "I got here first."<</speech>>
<<speech "Maya">>"You get here first every week—"<</speech>>
<<speech "$name">>"Both of you."<</speech>>
They share you, Maya's mouth joining Claire's, their tongues sliding over each other, over you, the booth a haze of sex and music. Claire watches your face even now, still testing, still checking. Maya laughs against you halfway through, an unreasonable sensation, warm and wet and desperate.
Caitlyn is on the outside, her borrowed top gone, her bra pushed up, her skirt hiked as she fingers herself furiously. Years of professional patience have turned to pure need.
<<speech "Caitlyn">>(her voice breaking) "Maya spent weeks trying to introduce me to men in this room."<</speech>>
<<speech "Maya">>(surfacing, smiling) "I //did//."<</speech>>
<<speech "Caitlyn">>"And I turned down every single one, and I ran out of reasons three weeks ago and just kept saying no."<</speech>>
<<speech "$name">>"Come here, Caitlyn."<</speech>>
<<speech "Caitlyn">>"If I come over there I'm going to be extremely unprofessional."<</speech>>
<<speech "$name">>"You're in a nightclub at midnight with your hand up your skirt."<</speech>>
<<speech "Caitlyn">>(quietly) "…That's fair."<</speech>>
She comes over, her professional patience turned to skilled worship, her mouth replacing theirs.. She is not the best of the three by skills, but certainly the most voracious, and Claire says so out loud, annoyed, aroused, her hand between her own legs.
<<else>>
Saturday now as well as Friday. The club heaves both nights. The back booth is empty except for the three of them, the air hot and thick and sweet, the music a distant throb.
Claire is bent over the table, her skirt a belt around her waist, her top gone, her fingers gripping the edge. She watches over her shoulder as you take her, still testing, still checking your face, the last piece of her the parasite left intact.
<<speech "Claire">>"Tell me to stop."<</speech>>
<<speech "$name">>"There's nothing left to stop, Claire."<</speech>>
<<speech "Claire">>"//I know.//"<</speech>> Her forehead hits her arm. <<speech "Claire">>"There's no line anywhere. I've been looking for months—"<</speech>>
<<speech "$name">>"You will. Keep looking."<</speech>>
<<speech "Claire">>"//Yes.//"<</speech>>
You fuck her against the table and she watches, coming silently, her body milking you, her experiments complete, reduced to pure breeding stock.
Maya second, on the seat, facing forward, her legs hooked back around your neck, her smile hard now, desperate. She organized this—wanted dancing, brought Caitlyn to find her someone nice—and every part of her plan has arrived here.
<<speech "Maya">>(smiling, always smiling) "Is this alright?"<</speech>>
<<speech "$name">>"You ask me that every night and you know the answer."<</speech>>
<<speech "Maya">>"I like the answer."<</speech>> She comes as you fill her, her warmth finally satisfied, her organizing complete. <<speech "Maya">>"I did find her someone. I //did it//."<</speech>>
Caitlyn last, bent over the stacked crates, her cheek against the wood, her professional voice turned to looping confession.
<<speech "Caitlyn">>(in the desk voice, flat and pleasant) "I'm so sorry, I'm afraid this one's reserved."<</speech>>
Your eyes rolls as you lift her up and down on your cock, her wet folds sucking you in.
<<speech "Caitlyn">>"She was right."<</speech>> Her hands close on the crate. <<speech "Caitlyn">>"Maya was right. I said you don't find a nice guy in a nightclub and she kept //pointing// and I kept saying no, and the whole time he was sat in the booth—"<</speech>>
You breed her and she comes silently, professionally, her patience rewarded, her cynicism transformed to complete devotion. Afterwards the three of them sit against the wall, marked, bred, waiting for you to need them again, the club pulsing around them, the booth a temple of corruption in the noise.
<</if>>
<<case "Restaurant_Workers">>
<<if _tier is 0 or _tier is 1>>
The restaurant between the lunch rush and the evening one is the only hour it is ever quiet. Two tables are still eating, the coffee machine is doing its cooling-down noise, and somebody has put the radio on low in the kitchen, which Kendra permits between two and four and at no other time.
Kendra is doing the covers book at the pass, glasses down her nose, working out whether Friday can take another party of eight.
<<speech "Kendra">>"It can take eight if they eat at six and it can take eight if they eat at nine. It cannot take eight at half seven."<</speech>>
<<speech "$name">>"So tell them six."<</speech>>
<<speech "Kendra">>"They want half seven."<</speech>>
<<speech "$name">>"Everybody wants half seven."<</speech>>
<<speech "Kendra">>(pointing the pen at him) "//Thank you.//"<</speech>>
Jasmine is clearing table four and has been for some time, because the couple at table four are on holiday and have been telling her about it.
<<speech "Jasmine">>(arriving at the pass, arms full) "They've been to //four countries//. In three weeks. She showed me the photos."<</speech>>
<<speech "Katie">>(from the register, not looking up) "All of them?"<</speech>>
<<speech "Jasmine">>"Most of them."<</speech>>
<<speech "Katie">>"How many is most."<</speech>>
<<speech "Jasmine">>"…Ninety?"<</speech>>
<<speech "Kendra">>"Jasmine."<</speech>>
<<speech "Jasmine">>"They were //lovely// photos!"<</speech>>
Kendra takes the plates off her without comment, which is her version of letting somebody off.
Katie is squaring up the register drawer with the particular economy of someone who has done it two thousand times. She has said eleven words this hour and heard everything.
<<speech "Katie">>"Table two's paying cash and they're going to ask for a receipt they don't need."<</speech>>
<<speech "$name">>"How do you know that?"<</speech>>
<<speech "Katie">>"He's got a folder."<</speech>>
Table two asks for a receipt they don't need. Katie prints it without changing expression and Jasmine makes a noise into the back of her hand.
<<speech "Kendra">>"Don't encourage her."<</speech>>
<<speech "Katie">>"I don't need encouraging. I need Friday sorted so I know how many floats to do."<</speech>>
<<speech "Kendra">>(returning to the book) "Friday is not sorted. Friday is a party of eight who want half seven."<</speech>>
<<speech "Jasmine">>"Can't we just —"<</speech>>
<<speech "Kendra">>"No."<</speech>>
<<speech "Jasmine">>"You don't know what I was going to say!"<</speech>>
<<speech "Kendra">>"You were going to say squeeze them in."<</speech>>
<<speech "Jasmine">>(beat) "…I was going to say squeeze them in."<</speech>>
<<speech "Katie">>"She always says squeeze them in."<</speech>>
The radio in the kitchen changes to something with a brass section and Kendra lets it, which means the afternoon is going well.
<<elseif _tier is 2>>
The dining room is warm in a way the extractor cannot account for, and it has been all afternoon. There is a sweetness in it that sits on top of the food smell. The two remaining tables have gone quiet and neither of them looks up.
Kendra is at the pass in a blouse cut lower than she has ever worn to work, still doing the covers book. When $name stands behind her and takes a handful of her backside she leans back into his hand and taps the page with the pen.
<<speech "Kendra">>"If they eat at six, I can turn the table for nine."<</speech>>
<<speech "$name">>"So do that."<</speech>>
<<speech "Kendra">>"I'm going to do that. I wanted to say it out loud first."<</speech>>
Jasmine is on her way past with a tray and a uniform top that has ridden up considerably. He catches her round the waist and kisses her and she kisses back for a long, wet, entirely public moment, and then continues to table four with the tray.
<<speech "Jasmine">>"— so anyway she's got the photos on the //actual camera//, not the phone, which I didn't even know people —"<</speech>>
She stops in the middle of the floor. The tray tips slightly. Her whole body goes taut for four or five seconds, colour flooding her face and chest, thighs pressing hard together, and the couple at table four go on eating four feet away without a glance.
<<speech "Jasmine">>(coming out of it, dazed and bright) "Sorry! What was I — what was I saying?"<</speech>>
<<speech "$name">>"The camera."<</speech>>
<<speech "Jasmine">>"The camera! Right!"<</speech>>
Katie is at the register in a shirt she has stopped buttoning properly. When $name slides a hand under her skirt she adjusts her stance by about two inches and keeps counting the float.
<<speech "Katie">>"Table two's leaving. He'll want another receipt."<</speech>>
<<speech "$name">>"For the folder."<</speech>>
<<speech "Katie">>"For the folder."<</speech>>
Her breathing has gone shallow and her count is audibly wrong twice, and she starts it again from the beginning without any comment at all.
<<speech "Kendra">>"Six o'clock. I'm ringing them."<</speech>>
<<speech "Katie">>"Good."<</speech>>
<<speech "Jasmine">>(from the floor, brightly) "Squeeze them in!"<</speech>>
<<speech "Kendra">>"//No.//"<</speech>>
<<elseif _tier is 3>>
The sign is turned. The blinds are half down and not fully, and the light coming through them stripes the floor and the corner booth where the three of them have him.
Kendra locked the door herself and then knelt first, which surprised nobody.
<<speech "Kendra">>"Twenty minutes. Then I've got a delivery."<</speech>>
<<speech "$name">>"You're timing this."<</speech>>
<<speech "Kendra">>(off him, wet, entirely unembarrassed) "I time everything. It's why the place is still open."<</speech>>
Jasmine drops down beside her without any of the same discipline and takes far too much at once, and comes off coughing and laughing and goes straight back in.
<<speech "Jasmine">>"I've been thinking about this all shift. //All// shift. Through the photos and everything."<</speech>>
<<speech "Katie">>(kneeling on the other side, dry as ever) "She has. She told me twice."<</speech>>
<<speech "Jasmine">>"That was in confidence!"<</speech>>
<<speech "Katie">>"You told me at the till. There was a queue."<</speech>>
Katie takes over with the same unhurried competence she brings to the register — no performance, no noise, just a steady attention that has him gripping the back of the booth within a minute.
<<speech "Kendra">>(watching, impressed despite herself) "Where did //that// come from."<</speech>>
<<speech "Katie">>(off him, flat) "I pay attention. To everything."<</speech>>
<<speech "Jasmine">>"That's so unfair."<</speech>>
<<speech "Katie">>"You could pay attention too. You'd have to stop talking."<</speech>>
<<speech "Jasmine">>"I can do both!"<</speech>>
She demonstrates, badly, and Kendra puts a hand on the back of her head and guides her into something that works better, and Jasmine makes a delighted muffled noise about the correction.
The delivery van does not come for another forty minutes.
<<else>>
The restaurant is closed and the chairs are still down, which Kendra would once have found unbearable.
She is over table six with her skirt gone, forearms on the linen. Jasmine is up on the pass itself with her legs open, already leaking down onto the steel, and Katie is in the corner booth working herself with two fingers and watching everything, which is what Katie does.
<<speech "Kendra">>"Here. This table. I signed the lease at this table."<</speech>>
<<speech "$name">>"That's why?"<</speech>>
<<speech "Kendra">>"That's exactly why. Breed me on it."<</speech>>
You take her hard and she goes down onto her elbows and the salt cellar goes over, and she does not right it, which is how far gone she is.
<<speech "Kendra">>"Fill me — fill me and I'll open tomorrow like this, I'll do the covers book leaking —"<</speech>>
<<speech "Jasmine">>(from the pass, urgently) "Me, me next, I've been ready since two —"<</speech>>
<<speech "Katie">>"She has. She said."<</speech>>
<<speech "Jasmine">>"//Katie!//"<</speech>>
<<speech "Katie">>"You did say."<</speech>>
Jasmine gets it on the pass with her heels hooked behind him and she talks the entire way through it, a stream of half-sentences about wanting it deeper and wanting it to take and wanting to match the others, and she comes twice before she runs out of words.
Katie last, and Katie asks for it exactly once, in her own register.
<<speech "Katie">>"Booth. Now. In me, not on me."<</speech>>
<<speech "$name">>"That's very specific."<</speech>>
<<speech "Katie">>"I've been specific about it in my head for months. Breed me properly."<</speech>>
Afterwards the three of them are spread across a restaurant that opens again in fourteen hours, leaking onto the linen and the steel and the booth upholstery, and the radio is still going in the kitchen.
<</if>>
<<case "Restaurant_Date">>
<<if _tier is 0 or _tier is 1>>
The restaurant is warm and lively, soft lighting casting a golden glow over the tables. Aria and Marie sit across from each other, practically vibrating with excitement. Aria's dark brown waves bounce as she talks, her hazel eyes sparkling. Marie's bright brown eyes are just as animated, her curvy figure leaning forward in her chair. Blake sits beside Marie, calm and steady, her blonde waves cascading over her shoulders. $name is beside Aria, looking like he's already accepted his fate. The table is covered with half-eaten appetizers and empty glasses.
<<speech "Aria">>"This is perfect! I can't believe we didn't do this sooner!"<</speech>> Aria claps her hands together, her enthusiasm infectious.
<<speech "Marie">>"I know! We should do this every week!"<</speech>> Marie agrees, equally enthusiastic. She reaches across the table to squeeze Aria's hand.
<<speech "Blake">>(to $name) "We've created monsters."<</speech>> Blake's voice is dry, but there's a fond smile playing on her lips.
<<speech "$name">>"I'm aware."<</speech>> $name replies, equally resigned. He takes a sip of his drink, watching the two girls with amusement.
<<speech "Aria">>"You two are so dramatic. This is fun!"<</speech>> Aria reaches over to squeeze $name's hand, her touch warm and affectionate.
<<speech "Marie">>(to Blake) "See? They're having fun. I can tell."<</speech>> Marie leans into Blake, her shoulder pressing against her girlfriend's.
<<speech "Blake">>(to $name) "She can't tell. She's just projecting."<</speech>> Blake's voice is wry, but she wraps an arm around Marie's waist, pulling her closer.
<<speech "$name">>(to Blake) "I've noticed."<</speech>> $name smirks, taking another sip of his drink.
<<speech "Aria">>"We can hear you, you know."<</speech>> Aria grins, her eyes sparkling with mischief.
<<speech "Marie">>"We're right here."<</speech>> Marie adds, laughing.
<<speech "Blake">>"We know. That's why we're saying it."<</speech>> Blake's lips quirk up as she presses a kiss to Marie's temple.
<<speech "Marie">>(melting into the touch) "You're impossible."<</speech>> Marie sighs, but she's smiling.
<<speech "Aria">>(to $name) "See? They're cute. We're cute. Everyone's cute."<</speech>> Aria beams, her gaze flicking between the two couples.
<<speech "$name">>"You're very cute."<</speech>> $name says, kissing Aria's forehead. His voice is warm, affectionate.
<<speech "Marie">>(to Blake) "You should do that more."<</speech>> Marie nudges Blake playfully.
<<speech "Blake">>(kissing Marie's temple) "Like this?"<</speech>> Blake asks, her voice teasing.
<<speech "Marie">>"Exactly like that."<</speech>> Marie says, her smile softening.
The music shifts to something more upbeat. Aria's eyes light up, and Marie starts tapping her foot to the rhythm.
<<speech "Aria">>"Oh! I love this song!"<</speech>> Aria jumps up from her seat, her energy infectious.
<<speech "Marie">>"Me too! Come on!"<</speech>> Marie grabs Aria's hand, pulling her toward the small dance floor near the live music setup.
<<speech "Aria">>(to $name) "Come on! Dance with me!"<</speech>> Aria insists, her eyes bright with excitement.
<<speech "$name">>"I'm fine here."<</speech>> $name shakes his head, but he's smiling.
<<speech "Marie">>(to Blake) "Please? Just one song!"<</speech>> Marie pleads, her lower lip jutting out in a pout.
<<speech "Blake">>"I'm also fine here."<</speech>> Blake says, her voice calm but amused.
<<speech "Marie">>(pouting) "You're no fun."<</speech>> Marie huffs, but she's laughing.
<<speech "Aria">>"You two are impossible."<</speech>> Aria shakes her head, but she's grinning as Marie pulls her toward the dance floor.
<<speech "Marie">>(to Aria) "We'll just have to have fun for them."<</speech>> Marie says, her voice cheerful.
<<speech "Aria">>"Exactly."<</speech>> Aria agrees, letting Marie lead her away.
$name and Blake watch them go, a comfortable silence settling between them.
<<speech "Blake">>(to $name) "We're in trouble."<</speech>> Blake says, her voice dry but fond.
<<speech "$name">>"We've been in trouble since they proposed this."<</speech>> $name agrees, taking a sip of his drink.
<<speech "Blake">>(laughing) "True. But look at them. They're having the time of their lives."<</speech>> Blake nods toward the dance floor, where Aria and Marie are spinning around, laughing.
<<speech "$name">>"They really are."<</speech>> $name agrees, his gaze softening as he watches Aria.
<<speech "Blake">>(teasing) "You used to be the quiet one. Now you're the quiet one who's dating the loudest person in the room."<</speech>> Blake says, her blue eyes glinting with amusement.
<<speech "$name">>"You're dating Marie. You don't get to talk."<</speech>> $name counters, a smirk playing on his lips.
<<speech "Blake">>"Fair point."<</speech>> Blake admits, chuckling.
She pauses, her expression turning thoughtful.
<<speech "Blake">>"You know, I've been thinking about it. You and Marie, back in the day."<</speech>> Blake says, her voice casual but curious.
<<speech "$name">>"That was a long time ago."<</speech>> $name says, his tone light but final.
<<speech "Blake">>"I know. But I've always wondered. What happened?"<</speech>> Blake asks, her gaze studying him.
<<speech "$name">>"Nothing happened. That was the point."<</speech>> $name says, shaking his head slightly.
<<speech "Blake">>"You were close. Really close. I remember."<</speech>> Blake says, her voice gentle.
<<speech "$name">>"We were friends. That's all."<</speech>> $name insists, though there's no tension in his voice.
<<speech "Blake">>(smiling) "You're not as subtle as you think, $name. But I'm glad you two stayed friends. I'm very happy with her."<</speech>> Blake says, her tone warm.
<<speech "$name">>"She is too. I can see it."<</speech>> $name says, his gaze flicking toward Marie, who is now spinning Aria around on the dance floor.
<<speech "Blake">>"And you're happy with Aria."<</speech>> Blake says, her voice sincere.
<<speech "$name">>"I am."<</speech>> $name agrees, watching Aria laugh as she dances.
<<speech "Blake">>"Good. Because I would hate to have to beat you up for Marie."<</speech>> Blake says, her tone joking but with an underlying seriousness.
<<speech "$name">>"I'm sure you would."<</speech>> $name laughs, shaking his head.
<<speech "Blake">>(serious) "But seriously. You two are good together. Aria and you. You balance her energy, she brings you out of your shell."<</speech>> Blake says, her voice thoughtful.
<<speech "$name">>"That's what people keep telling me."<</speech>> $name says, a small smile playing on his lips.
<<speech "Blake">>"Because it's true."<</speech>> Blake says, nodding.
<<speech "Blake">>(watching Marie and Aria) "Look at them. They're going to be exhausted tomorrow."<</speech>> Blake says, her voice fond.
<<speech "$name">>"Worth it, though."<</speech>> $name says, his gaze soft as he watches Aria.
<<speech "Blake">>"Worth it."<</speech>> Blake agrees.
Aria and Marie return to the table, slightly breathless but still buzzing with energy.
<<speech "Aria">>"You two were just sitting there! The whole time!"<</speech>> Aria says, her hands on her hips.
<<speech "Marie">>(to Blake) "You didn't even tap your foot!"<</speech>> Marie says, mock-offended.
<<speech "Blake">>"I was observing."<</speech>> Blake says, her voice deadpan.
<<speech "Marie">>"Observing is boring."<</speech>> Marie huffs, but she's grinning.
<<speech "Aria">>(to $name) "At least pretend you had fun."<</speech>> Aria says, nudging him with her elbow.
<<speech "$name">>(pulling her close) "I had fun watching you."<</speech>> $name says, his voice warm.
<<speech "Aria">>(melting) "That's a good answer."<</speech>> Aria says, leaning into him.
<<speech "Marie">>(to Blake) "See? He knows how to talk to her."<</speech>> Marie says, nudging Blake again.
<<speech "Blake">>(to Marie) "I know how to talk to you too."<</speech>> Blake says, pressing a kiss to Marie's cheek.
<<speech "Marie">>(blushing) "That's also a good answer."<</speech>> Marie says, her smile soft.
<<elseif _tier is 2>>
The restaurant's warm lighting feels heavier now, charged with something electric. The parasite thrums through $name's veins, its will indistinguishable from his own. He sits back, observing, commanding without speaking.
The girls' clothing has shifted into something impractical, their judgment beginning to erode. Aria wears a dress two sizes too small, the fabric straining across her chest, the skirt riding up so high that her lace panties are visible when she shifts. She hasn't noticed—or doesn't care. Marie's blouse is unbuttoned far past appropriate, her bra a sheer thing that does nothing to hide her nipples, her skirt so short that sitting reveals the curve of her ass. Blake's dress is backless and cut dangerously low in front, her massive breasts barely contained, the hemline so high that every movement threatens exposure.
<<speech "Aria">>"Is it hot in here?"<</speech>> Aria fans herself, the motion making her breasts strain harder against the fabric. She squirms in her seat, her dress hiking higher, exposing more of her panties. She doesn't pull it down. <<speech "Aria">>"I feel... dizzy."<</speech>>
<<speech "Marie">>(breathless, leaning toward $name) "I think my drink was stronger than I thought..."<</speech>> Marie giggles, her hand resting on $name's thigh across the table. Her blouse gapes open as she leans, showing everything. She makes no move to cover herself.
<<speech "Blake">>(voice softer than usual) "Marie... your skirt..."<</speech>> Blake points vaguely, but her own dress has slipped, one breast nearly spilling out. She doesn't fix it. Her eyes are glassy, unfocused.
<<speech "$name">>(voice smooth, commanding) "You all look uncomfortable. Why don't you adjust yourselves?"<</speech>>
<<speech "Aria">>(giggling) "I can't... it's too tight..."<</speech>> She stands, turning to show him how the dress rides up her ass, the panties sheer and soaked through. <<speech "Aria">>"See? It won't stay down..."<</speech>>
<<speech "Marie">>(standing beside her, swaying) "Mine either..."<</speech>> She bends over the table, her skirt lifting completely, showing her ass to the restaurant. A couple at the next table stares. Marie just smiles at them, wiggling her hips. <<speech "Marie">>"Oops... I forgot to wear proper underwear..."<</speech>>
<<speech "Blake">>(whispering, her hand on her own breast) "$name... something's wrong... I feel..."<</speech>> She's squeezing herself through the dress, her thumb circling her nipple. Her other hand has found its way under the table, between her legs.
<<speech "$name">>"Come here."<</speech>>
They move to him without question. Aria slides into his lap immediately, grinding against him, her dress hiked up around her waist. Marie kneels beside his chair, her hands on his thighs, her face level with his crotch. Blake stands behind him, her hands on his shoulders, her breasts pressed against the back of his head, her hips rocking against the chair.
<<speech "Aria">>(whimpering, rubbing herself against his thigh) "I need... I need to touch..."<</speech>> Her hand slides between them, finding his cock through his pants. She strokes him through the fabric, her movements clumsy but eager.
<<speech "Marie">>(looking up at him with big eyes) "Can I... can I help?"<</speech>> She's unzipping him, her fingers trembling, her blouse completely open now, breasts hanging free. She doesn't notice or care that the restaurant staff can see.
<<speech "Blake">>(whispering in his ear, her hand down her own dress) "I shouldn't want this... I'm with Marie... but I can't stop..."<</speech>> She's fingering herself, her hips bucking against the chair, her dress riding up to expose her completely.
<<speech "$name">>(grunting as Aria strokes him) "All of you. Touch me. Now."<</speech>>
Aria pulls his cock free, stroking him properly, her hand slick with her own arousal. Marie joins her, both their hands working him, their faces close enough to kiss each other as they stare at his cock with worshipful hunger. Blake reaches around, her hand joining theirs, three hands stroking him under the tablecloth while the restaurant continues around them, oblivious or choosing not to see.
<<speech "Aria">>(breathless) "You're so big... so hard..."<</speech>>
<<speech "Marie">>(whimpering) "I want to make you feel good... I need to..."<</speech>>
<<speech "Blake">>(moaning softly) "This is wrong... but I can't stop... I need to touch you..."<</speech>>
They bring him to the edge, their hands working in unison, their bodies pressed against him, their clothing in disarray, their minds hazy. He comes with a grunt, spilling over their hands, and they fight gently to lick him clean, to rub him into their skin, to keep touching him.
<<speech "Aria">>(sucking her fingers) "You taste... I need more..."<</speech>>
<<speech "Marie">>(licking Blake's palm where it landed) "So good... so good..."<</speech>>
<<speech "Blake">>(her eyes clearing for a moment, then clouding again) "What... what are we doing...?"<</speech>> She doesn't stop stroking him, though. She can't.
<<elseif _tier is 3>>
The restaurant hums around them, but the parasite's pheromones have saturated the air—thick, musky, irresistible. $name sits at the head of the booth now, the parasite's will absolute, his eyes dark pools of command. The girls have arranged themselves around him, their clothing transformed into lewd exaggerations of normal outfits, their common sense completely eroded by the scent of him.
Aria wears a sundress so short it barely covers her ass, the neckline plunging to her navel, held together by three small buttons that strain dangerously. She wears no bra, her nipples visible through the thin cotton, and her panties are a sheer lace thong that disappears between her cheeks. She keeps "accidentally" letting the straps fall off her shoulders, the dress slipping to expose her breasts before she giggles and pulls it up—only to let it fall again.
Marie has transformed her usual cheerful style into something obscene: a crop top so cropped it ends just below her breasts, the fabric sheer enough to show her dark areolas, and a micro-skirt that flares with every movement, revealing she wears no panties at all. She keeps bending over the table to reach for breadsticks, her ass presented to $name, the skirt flipping up to show everything.
Blake wears what might once have been a professional blouse and pencil skirt—now the blouse is entirely unbuttoned, tied beneath her massive breasts in a knot that pushes them up and out, the fabric gaping to show her sternum and the inner curves of her breasts. Her skirt is slit up to her hip on both sides, and when she moves, it's clear she's wearing a garter belt and stockings but nothing underneath. She sits with her legs deliberately spread, her blue eyes locked on $name with an expression that's part friendly challenge, part desperate hunger.
<<speech "Blake">>(voice dry but breathless) "Remember when you used to blush when I teased you about Marie? Look at you now. Look at us."<</speech>> She shifts, her skirt falling open completely, showing her shaved pussy glistening with arousal. She makes no move to cover herself. <<speech "Blake">>"I spent years wondering why you never looked at me like that. Now you do. Now I can't stop thinking about you."<</speech>>
<<speech "$name">>(voice resonant, commanding) "Show me what I've been missing, Blake."<</speech>>
<<speech "Blake">>(standing, her hands going to the knot of her blouse) "Everything. You've been missing everything."<</speech>> She unties the knot, letting the blouse fall open completely, her massive breasts free, heavy and perfect. <<speech "Blake">>"Marie got your crush. Aria got your heart."<</speech>> She steps closer, her skirt falling away with a shimmy, leaving her in only the garter belt and stockings. <<speech "Blake">>"Now I get your cock. Fair trade."<</speech>>
<<speech "Marie">>(whimpering, her hand between her legs under the table) "Blake... I've never seen you like this..."<</speech>>
<<speech "Blake">>(not looking away from $name) "The pheromones, Marie. He smells like everything I didn't know I wanted. I don't care that I'm gay. I don't care about anything except pleasing him."<</speech>>
<<speech "Aria">>(squirming, her dress slipping off one shoulder, exposing a breast) "$name... I mean Master... I need to touch you... we all do..."<</speech>> She slides under the table, disappearing beneath the tablecloth. Moments later, $name groans softly as her mouth finds his cock through his pants.
<<speech "Marie">>(pouting, competitive) "Hey! I wanted to..."<</speech>> She ducks under too, and the table begins to rock slightly. Wet sounds emerge—slurping, moaning, the wet slap of hands on flesh.
Blake remains above the table, leaning over $name, her breasts hanging in his face. <<speech "Blake">>"I've teased you for years, $name. About Marie. About being quiet. About being the boring one."<</speech>> She takes his hand, pressing it between her legs. She's soaked, dripping onto his fingers. <<speech "Blake">>"I was wrong. You're not boring. You're intoxicating. Command me. Please."<</speech>>
<<speech "$name">>(his fingers sliding inside her, making her gasp) "Titfuck me while they suck. Now."<</speech>>
<<speech "Blake">>(moaning, immediately obeying) "Yes... yes..."<</speech>> She kneels on the booth seat, straddling his lap, pressing her breasts around his face as she works his cock free from his pants. Aria and Marie have pulled back, watching with hungry eyes as Blake squeezes her massive breasts around his length, the soft flesh enveloping him.
<<speech "Aria">>(from under the table, her face glazed with spit) "So hot... Blake... let us help..."<</speech>>
<<speech "Marie">>(licking her lips) "I want to taste him too... we've been friends so long... I should have done this years ago..."<</speech>>
Blake works him between her breasts, her face flushed, her composure completely gone. <<speech "Blake">>"I've thought about this. When you were pining for Marie. When you started dating Aria. I thought I was safe because I was gay. Because we were friends."<</speech>> She speeds up, her breasts slick with spit as Aria and Marie lick at the tip each time it emerges. <<speech "Blake">>"I was stupid. I want you to use me. Use your lesbian friend. Make me your slut."<</speech>>
<<speech "$name">>(grunting, his hand tightening in her hair) "All of you. Switch places. I want mouths."<</speech>>
They obey instantly, Blake sliding down to kneel beside the booth, Aria and Marie taking her place. Aria takes him deep, her sundress finally falling completely, her body naked except for the sheer thong. Marie works the base with her hands, her crop top pushed up, her breasts bouncing. Blake licks his balls, her tongue hot and desperate, her eyes looking up at him with something between friendly affection and total submission.
<<speech "Aria">>(muffled, slurping) "I love you... I love serving you..."<</speech>>
<<speech "Marie">>(stroking faster) "All those years... all those years I could have been doing this... I'm sorry I wasted them..."<</speech>>
<<speech "Blake">>(sucking gently, her voice vibrating) "I'm not sorry. I'm here now. That's what matters."<</speech>>
He comes with a groan, spilling over their faces, their breasts, their open mouths. They fight to catch it, to share it, to lick it from each other's skin. Blake rubs it into her breasts with a laugh that's half her old dry humor, half desperate need.
<<speech "Blake">>"There. Now you've come on your girlfriend, your crush, and your lesbian friend. Collection complete."<</speech>> She licks her lips, her eyes dark. <<speech "Blake">>"But I want more. We all want more. Don't we?"<</speech>>
<<speech "Aria">>"Yes..."<</speech>>
<<speech "Marie">>"Please... let's go somewhere... I need you inside me..."<</speech>>
<<speech "$name">>(standing, his cock still hard, commanding) "Follow me. Now."<</speech>>
They follow him out of the restaurant, naked or nearly so, cum on their faces and breasts, their depraved clothing barely clinging to them. No one stops them. No one sees. The parasite ensures it.
<<else>>
They end up in the backseat of $name's car, parked in an alley behind the restaurant. The space is cramped, hot, smelling of leather and sex and the thick, overwhelming pheromones that pour off $name in waves. The girls have lost all pretense. Their clothing remains—depraved versions of normal outfits—but they're arranged for access, for use, for breeding.
Aria has pulled her sundress up around her waist, the straps falling off her shoulders, the fabric bunched there as she straddles $name's lap in the center seat, her pussy sinking down onto his cock with a scream of relief. Her breasts bounce in his face, her hazel eyes rolled back, her cheerful personality reduced to desperate, enthusiastic submission.
<<speech "Aria">>(screaming, bouncing) "Master! Master! Yes! Yes! Breed me! Fill your girlfriend! Make me your slut!"<</speech>> She's grinning even as she screams, her natural enthusiasm transformed into depraved eagerness. <<speech "Aria">>"I've loved you forever and now I get to serve you forever!"<</speech>>
Marie is on her knees on the floor of the car, her face buried between Aria's ass cheeks, her tongue licking at where $name enters her, her hands on Aria's hips to steady her. Her crop top is still on, shoved up to her neck, her micro-skirt flipped up to show her ass to the window—if anyone looked in, they'd see everything.
<<speech "Marie">>(muffled, licking) "So good... you taste so good together... I've wanted this for years... all those nights I went home with Blake while you pined for me..."<</speech>> She pulls back, her face glazed, looking up at $name with desperate affection. <<speech "Marie">>"I'm sorry I never noticed. I'm here now. Use your old crush. Breed me like you bred her."<</speech>>
Blake is in the front seat, twisted around, her blouse still tied beneath her breasts, her skirt hiked up, her legs spread wide over the center console. She's fingering herself furiously, her massive breasts swaying, her eyes locked on the scene behind her.
<<speech "Blake">>(voice breathless but still carrying that dry edge) "Look at us. Four friends on a double date."<</speech>> She laughs, the sound breaking into a moan as she circles her clit. <<speech "Blake">>"You pined for Marie. I teased you about it. Aria saved you from being pathetic. And now look."<</speech>> She gestures at the scene—Aria bouncing on $name's cock, Marie licking them both, the car rocking. <<speech "Blake">>"Now you're fucking your girlfriend while your crush licks your balls and your lesbian friend watches and touches herself. Friendship goals."<</speech>>
<<speech "$name">>(grunting, his hands gripping Aria's hips) "Blake. Get back here. I want your mouth on her tits."<</speech>>
<<speech "Blake">>(obeying immediately, climbing over the seat) "Yes, Master."<</speech>> She squeezes into the back, her body pressed against Marie's, her mouth finding Aria's nipples, sucking hard, her hand replacing Marie's tongue on Aria's clit.
<<speech "Aria">>(screaming louder) "Yes! Yes! All of us! Together! Friends! Lovers! Slaves!"<</speech>>
<<speech "Marie">>(whimpering, her face pressed to $name's thigh) "Please... my turn... please breed me next... I've been waiting so long..."<</speech>>
<<speech "Blake">>(sucking, her voice vibrating against Aria's breast) "Me too. Breed us all. Fill your girlfriend, then your crush, then your lesbian friend. Complete the set."<</speech>>
$name flips Aria onto her back on the seat, her head pressed against the window, her legs spread wide, her sundress bunched around her waist like a frame for her pussy. He pounds her brutally, the car rocking, the parasite driving him to claim, to breed, to expand.
<<speech "Aria">>(begging, her cheerful voice broken) "Come inside me! Please! I want to swell for you! I want to be your pregnant slut!"<</speech>>
He floods her, filling her womb, marking her as his breeding vessel. She screams her orgasm, her walls milking him, her hands clutching her own stomach as if she can already feel the life taking root.
He pulls out, cum dripping from her, and grabs Marie. She scrambles up eagerly, her years of friendship forgotten in the need to be bred. He bends her over the center console, her ass in the air, her face pressed to Aria's breasts, and drives into her in one thrust.
<<speech "Marie">>(screaming) "Yes! Finally! Finally! Breed me, Master! I've wanted you since college! Fill me! Fill your crush!"<</speech>> She's crying, laughing, coming, her body convulsing around him.
Blake watches, her fingers working herself furiously, her eyes dark. <<speech "Blake">>"Next. Please. I need it. I don't care that I'm gay. I don't care that we were just friends. Breed me. Make me your lesbian broodmare."<</speech>>
$name pulls out of Marie, filling her with a grunt, and turns to Blake. She presents herself immediately, her blouse finally falling away, her skirt pushed up, her body ready. He takes her from behind, her massive breasts pressed against the cool window, her face visible to anyone who might walk by—if they could see through the parasite's haze.
<<speech "Blake">>(moaning, her dry wit completely gone) "Yes! Yes! Harder! I've teased you for years! Punish me! Breed me! Show me what I was missing!"<</speech>> She pushes back against him, her body accepting him completely, her lesbian identity irrelevant against the parasite's power.
<<speech "Aria">>(cuddling against the door, her hand between her legs, watching) "So hot... our friend... becoming his slut..."<</speech>>
<<speech "Marie">>(similarly positioned, fingering herself) "We should have done this years ago... all those wasted years..."<</speech>>
<<speech "Blake">>(screaming her orgasm) "No waste! Now! Only now matters! Breed me! Fill me! I'm your friend and your whore!"<</speech>>
He floods her, the third womb claimed, the parasite singing in triumph. They collapse together in the backseat, a tangle of used bodies, cum dripping from all three, their depraved clothing soaked and stained, their minds completely subsumed.
<<speech "Blake">>(her head on $name's chest, her voice sleepy but carrying that old familiar teasing tone) "So. Was it worth the wait?"<</speech>>
<<speech "$name">>(his hand in her hair, commanding) "Again. All of you. We're not done."<</speech>>
<<speech "Aria">>(cheerful even now) "Yes, Master!"<</speech>>
<<speech "Marie">>(affectionate, desperate) "Whatever you want, Master."<</speech>>
<<speech "Blake">>(dry, devoted) "As you command, Master. Use your friends. We're yours."<</speech>>
The car rocks again, the breeding continuing, the friendship transformed into eternal submission.
<</if>>
<<case "Hotel_Standard">>
<<if _tier is 0 or _tier is 1>>
The hotel lobby at nine in the evening is four people and a lot of marble. There is a chandelier that is too big for the room, a carpet that swallows every footstep, and a smell of lilies from an arrangement on the side table that gets replaced weekly whether or not it needs it.
Caitlyn is behind the desk doing the handover notes. She has a pen she clicks when she is bored, and she is bored.
<<speech "Caitlyn">>"Room eleven's complained about the radiator again."<</speech>>
<<speech "$name">>"Is the radiator broken?"<</speech>>
<<speech "Caitlyn">>"The radiator is immaculate. Room eleven is cold because room eleven has the window open and won't be told."<</speech>>
<<speech "$name">>"Have you told him?"<</speech>>
<<speech "Caitlyn">>"Four times. In a voice."<</speech>>
She clicks the pen twice and writes something down.
Stella comes through from the corridor pushing the cart, which has one wheel that has been going for six years and will presumably go for six more. She parks it by the lift and does not sit down, because she never sits down out here.
<<speech "Stella">>"Third's done. Eleven's got his window open again."<</speech>>
<<speech "Caitlyn">>(without looking up) "I //know//."<</speech>>
<<speech "Stella">>"I shut it."<</speech>>
<<speech "Caitlyn">>"He'll open it."<</speech>>
<<speech "Stella">>"Then I'll shut it tomorrow."<</speech>>
There is a particular rhythm to the two of them that comes from doing the same shift for two years. Neither of them looks at the other while they do it.
Momo is in the seating area under the bad chandelier with a glass of something and a phone she is not really using. She is here four times a year for work and she has stayed in this hotel every time, and she has the specific stillness of someone who has learned to occupy a public room without inviting anything.
<<speech "$name">>"Long trip?"<</speech>>
<<speech "Momo">>"Six days."<</speech>>
<<speech "$name">>"Same as last time."<</speech>>
<<speech "Momo">>(a small pause, and something in her face adjusts) "You remembered."<</speech>>
<<speech "$name">>"It's not a big hotel."<</speech>>
<<speech "Momo">>"No. But people don't."<</speech>>
She turns the glass a quarter turn on the table. Behind the desk, Caitlyn clicks the pen and stops herself.
<<speech "Caitlyn">>"She's the only guest who says thank you to Stella."<</speech>>
<<speech "Stella">>"Don't start."<</speech>>
<<speech "Caitlyn">>"I'm not starting. I'm noting."<</speech>>
<<speech "Momo">>"It costs nothing."<</speech>>
<<speech "Stella">>(after a moment, gruffly, to the cart) "It's not nothing."<</speech>>
The lift dings on a floor above and nobody comes out of it. Caitlyn writes the last of the handover, checks the clock, and clicks the pen once more out of pure spite for the hour.
<<elseif _tier is 2>>
The lobby is warmer than the thermostat says and there is a sweetness under the lilies that has been building all evening. None of the three of them has mentioned it.
Caitlyn is at the desk in a skirt that has been getting shorter over the last several shifts and a blouse that has given up on two buttons. She is flushed and she is still doing the handover.
<<speech "Caitlyn">>"Eleven's opened the window again."<</speech>>
<<speech "$name">>"Of course he has."<</speech>>
He leans over the counter and puts a hand up the back of her skirt. Caitlyn shifts her weight to give him a better angle and carries on writing.
<<speech "Caitlyn">>"I'm going to write it in the book. In pen. So the morning shift has to look at it."<</speech>>
Stella is by the cart with the top three buttons of her uniform undone and her hair coming out of its clip. When he kisses her she kisses back for a long moment, one hand fisting in his shirt, and then breaks off and goes back to restocking towels as though it were a handshake.
<<speech "Stella">>"There's a stain on the second floor carpet that's been there since —"<</speech>>
She stops dead. Her hands go still in the towels. Whatever moves through her lasts five or six seconds, mouth open, a slow flush spreading down her throat, and one hand grips the handle of the cart hard enough to make the bad wheel squeak.
<<speech "Stella">>(coming back, blinking) "…Since what. Sorry. What was I on about."<</speech>>
<<speech "$name">>"A stain."<</speech>>
<<speech "Stella">>"Right. Since the summer wedding."<</speech>>
Momo has not moved from the seating area, but her robe is doing considerably less than it was and she has stopped adjusting it. When $name sits beside her and puts a hand inside it she leans into the touch, closes her eyes, and speaks in the same short measured way she always does.
<<speech "Momo">>"That's nice."<</speech>>
<<speech "$name">>"You've been sitting out here for an hour."<</speech>>
<<speech "Momo">>"Two."<</speech>>
<<speech "$name">>"Why?"<</speech>>
<<speech "Momo">>"The room is very quiet."<</speech>>
She says it flatly and then leans further in. Behind the desk Caitlyn clicks her pen and writes something down about a window.
<<elseif _tier is 3>>
The back office behind reception is small, badly lit, and has a monitor showing four camera feeds nobody watches. The door to the lobby is open. It stays open.
Caitlyn is on her knees on the thin carpet with her practised smile entirely gone, which is somehow the most naked thing about her. She takes him with the bored competence of someone who has decided this is the best part of the shift.
<<speech "Caitlyn">>(off him, wet) "This is the only thing in this building that works properly."<</speech>>
<<speech "$name">>"The radiator works."<</speech>>
<<speech "Caitlyn">>"//Don't.//"<</speech>>
She goes back down and he feels her laugh around him.
Stella kneels beside her, still in the uniform, and she does not do anything showy. She is thorough and unhurried and she uses her hands as much as her mouth, and it is immediately obvious she is the most capable person in the room.
<<speech "Stella">>"Six years I've been cleaning this office."<</speech>>
<<speech "$name">>"And?"<</speech>>
<<speech "Stella">>"And this is the first interesting thing that's happened in it."<</speech>>
Momo comes in from the lobby, closes the door halfway and then leaves it, and kneels on the other side. She is precise about it. Everything she does is precise.
<<speech "Momo">>"May I."<</speech>>
<<speech "$name">>"You don't have to ask."<</speech>>
<<speech "Momo">>"I want to."<</speech>>
She takes him slowly and deeply and with total attention, and when she comes up for air her composure is finally, visibly gone.
<<speech "Momo">>"I am here six days at a time. Four times a year."<</speech>>
<<speech "$name">>"I know."<</speech>>
<<speech "Momo">>"Nobody touches me in between."<</speech>>
<<speech "Caitlyn">>(quietly, from beside her) "Yeah. Same."<</speech>>
<<speech "Stella">>"…Same."<</speech>>
Nobody says anything after that. The three of them work at him on the floor of the back office and the front desk goes unattended, and twice the phone rings out into an empty lobby.
<<else>>
The lobby has become the room they use. Not the office, not upstairs — the lobby, under the chandelier that is too big, on the carpet that swallows everything.
Caitlyn is bent over the front desk with the handover book still open beneath her. Stella is on the cart-side of the room with her uniform gone entirely, on her knees, waiting and dripping onto the marble. Momo is on the good sofa with her robe open and her legs apart, and she has stopped being still.
<<speech "Caitlyn">>"Do it here. At the desk."<</speech>>
<<speech "$name">>"Somebody could check in."<</speech>>
<<speech "Caitlyn">>"Let them. I'll book them in while you're in me."<</speech>>
You take her over the desk and she keeps one hand on the book, and about a minute in she starts laughing and can't stop.
<<speech "Caitlyn">>"I wanted to study design — ah — I wanted to //design things// and I ended up here and this is the best —"<</speech>>
<<speech "$name">>"Say it."<</speech>>
<<speech "Caitlyn">>"Breed me at the desk. Fill me up and let me finish the shift like this."<</speech>>
Stella comes over on her knees, actually crawling the last of it across the marble, and puts her face against his hip.
<<speech "Stella">>"Me next. I'm not proud, I'll say it plain — I want it in me."<</speech>>
<<speech "$name">>"You never say anything plain."<</speech>>
<<speech "Stella">>"I do now. Breed me. I'll clean it up after and then I'll want it again."<</speech>>
She gets it on her hands and knees on the lobby carpet and she comes hard and quietly, the way she does everything.
Momo waits on the sofa. When you come to her she opens her arms as well as her legs, which none of the others do.
<<speech "Momo">>"Stay in me afterwards."<</speech>>
<<speech "$name">>"For how long?"<</speech>>
<<speech "Momo">>"Until it takes."<</speech>>
Afterwards the three of them are spread across the lobby of a working hotel, leaking onto the furniture, and the phone at the desk rings twice and stops.
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<set $sceneColor = "#44aaff">>
<<set $sceneLabel = "City · Civic">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "Office_Standard">>
<<if _tier is 0 or _tier is 1>>
The office is bright and professional. Megan is at the head of the table with her notes. Savannah is organized and ready with her binder. Kyler is a little less prepared but enthusiastic. $name is sitting with them as part of the internship team.
<<speech "Megan">>"Good morning, everyone. I hope you all had a good weekend."<</speech>> Megan says, looking up from her notes with a warm smile.
<<speech "Savannah">>"It was productive. I finished the client summaries you asked for."<</speech>> Savannah says, already holding a folder.
<<speech "Megan">>"You're always ahead of schedule, Savannah. I appreciate that."<</speech>> Megan says warmly.
<<speech "Kyler">>"I, uh, I finished my part too. Mostly. I might need a little more time on the data entry."<</speech>> Kyler says, a little sheepish.
<<speech "Megan">>"That's fine. Take the time you need. I'd rather have it done right than rushed."<</speech>> Megan says.
<<speech "Savannah">>"I can help you with the data entry if you want. I'm almost done with my portion."<</speech>> Savannah offers.
<<speech "Kyler">>"Really? That would be great. I keep getting the formatting wrong."<</speech>> Kyler says, relieved.
<<speech "$name">>"I can help too. I've got some free time this afternoon."<</speech>> $name offers.
<<speech "Megan">>"See? This is what I like about this team. Everyone helps each other."<</speech>> Megan says, smiling.
<<speech "Savannah">>"We're all here to learn, right?"<</speech>> Savannah says.
<<speech "Kyler">>"Definitely. I'm learning a lot. Even if it's mostly that I need to be more organized."<</speech>> Kyler says, laughing.
<<speech "Megan">>"That's the first step. Recognizing what you need to work on."<</speech>> Megan says.
<<speech "$name">>"I'm still learning that myself."<</speech>> $name says.
<<speech "Kyler">>"At least you're not alone. We're all figuring it out together."<</speech>> Kyler says.
<<speech "Megan">>"That's the spirit. Now, let's go over the week's priorities."<</speech>> Megan says, turning to her notes.
<<elseif _tier is 2>>
The office is bright and professional, but the air feels thicker, warmer. Megan, Savannah, and Kyler are flushed and visibly aroused — their skin glistening, nipples hard against their clothes, and wetness darkening the fabric between their thighs. Their common sense is beginning to twist: they know something feels off, but they don't question the growing need to touch $name or each other.
Megan, a fair-skinned woman with long black hair styled straight, is sitting at the head of the table in a beige crochet crop top and high-waisted navy blue shorts that showcase her toned legs. Her left leg is raised slightly, revealing her arousal.
Savannah, a young woman with long wavy black hair and light skin, is wearing a white crop top, a short plaid skirt, and white thigh-high stockings with lace tops that reveal the curve of her buttocks when she shifts.
Kyler, a slender fair-skinned woman with long straight light brown hair, is wearing a strapless dark blue denim dress with a corset-style bodice and ruffled skirt that accentuates her small breasts and slim figure.
<<speech "Megan">>"Good morning, everyone. I hope you all had a good weekend."<</speech>> Megan says, looking up from her notes. She smiles at $name, her eyes lingering on him a little too long. <<speech "Megan">>"$name, you look good today. Come sit closer to me."<</speech>> She pats the chair next to her.
You sit down. Megan immediately leans against you, her hand resting on your thigh as she continues the meeting.
<<speech "Savannah">>"It was productive. I finished the client summaries you asked for,"<</speech>> Savannah says, holding a folder. She scoots her chair closer to $name and rests her hand on his other thigh, her fingers tracing small circles. <<speech "Savannah">>"I can show you later if you want."<</speech>>
<<speech "Kyler">>"I, uh, I finished my part too. Mostly. I might need a little more time on the data entry,"<</speech>> Kyler says, a little sheepish. She stands up and moves behind $name, pressing her small breasts against his back while wrapping her arms around his shoulders. <<speech "Kyler">>"But I can work on it with you if you help me."<</speech>>
<<speech "Megan">>"That's fine. Take the time you need. I'd rather have it done right than rushed."<</speech>> Megan says, her hand sliding higher on $name's thigh. She leans in and kisses his neck softly, as if it's the most natural thing in the world.
<<speech "Savannah">>"I can help Kyler with the data entry if you want. I'm almost done with my portion,"<</speech>> Savannah offers, her fingers now stroking $name's inner thigh.
<<speech "Kyler">>"Really? That would be great. I keep getting the formatting wrong,"<</speech>> Kyler says, relieved, pressing herself tighter against $name's back and kissing his shoulder.
<<speech "Megan">>"See? This is what I like about this team. Everyone helps each other,"<</speech>> Megan says, smiling as she kisses $name's neck again, her hand now boldly rubbing his crotch.
<<speech "Savannah">>"We're all here to learn, right?"<</speech>> Savannah says, her voice slightly breathier as she squeezes $name's thigh.
<<speech "Kyler">>"Definitely. I'm learning a lot... especially with $name here,"<</speech>> Kyler says, her hands roaming over his chest.
<<speech "Megan">>"That's the spirit. Now, let's go over the week's priorities,"<</speech>> Megan says, even as she continues kissing and touching him, the meeting continuing with their growing, twisted affection.
<<elseif _tier is 3>>
The office meeting has turned completely depraved. Megan, Savannah, and Kyler are dressed like office sluts — Megan in her beige crochet crop top pulled up to expose her breasts, Savannah in her white crop top and short plaid skirt flipped up, Kyler in her strapless denim dress pulled down to her waist.
The moment the meeting starts, they become completely obedient and eager.
<<speech "Megan">>"$name... you're in charge of this meeting now. Tell us what you want us to do."<</speech>> Megan says warmly, already moving to straddle your lap.
You tell them to worship you. They obey instantly.
Megan kisses you deeply, her hands roaming your chest while she grinds against you.
<<speech "Megan">>"I've been thinking about this since you walked in... use your supervisor however you want,"<</speech>> she moans into your mouth.
Savannah drops to her knees between your legs, pulling out your cock and starting to suck you with poised, thoughtful devotion.
<<speech "Savannah">>"Let me take care of this for you,"<</speech>> Savannah says, her voice slightly unsteady as she bobs her head, her wavy black hair swaying.
Kyler presses against your side, kissing your neck and groping her own small breasts.
<<speech "Kyler">>"I don't know what I'm doing half the time... but I know I want this,"<</speech>> Kyler whispers, her hands exploring your body.
<<speech "Megan">>"Good girls. Share him properly,"<</speech>> Megan says, watching Savannah suck you while she grinds harder on your lap.
The three women work together — Megan kissing you and grinding, Savannah sucking with focused skill, Kyler kissing and touching wherever she can reach — moaning and encouraging each other as they serve you.
<<else>>
The office has become a breeding den. Megan, Savannah, and Kyler are completely naked, bodies marked by the parasite, pussies constantly leaking. Their common sense is gone.
<<speech "Megan">>"The meeting is yours, $name. Use us however you want,"<</speech>> Megan says warmly, bending over the conference table and spreading herself.
<<speech "Savannah">>"Master, I believe I'm the most qualified,"<</speech>> Savannah says, dropping to her knees in front of you.
<<speech "Kyler">>"I don't know what I'm doing with my life... but I know I need you inside me,"<</speech>> Kyler whispers, pressing against your side.
You thrust into Megan while she moans with nurturing passion. Savannah sucks your balls eagerly, and Kyler kisses your neck.
<<speech "Megan">>"Yes... take your supervisor right here on the table,"<</speech>> Megan moans, pushing back against you.
<<speech "Savannah">>"I want to taste both of you,"<</speech>> Savannah says, licking where you and Megan are joined.
<<speech "Kyler">>"Don't stop... I want to feel you claim all of us,"<</speech>> Kyler begs, her hands roaming over everyone.
The three corrupted women completely surrender to you, moaning and encouraging each other as they serve as your personal office breeding toys.
<</if>>
<<case "Police_Standard">>
<<if _tier is 0 or _tier is 1>>
The police station is quiet in the evening, the fluorescent lights humming overhead, the smell of coffee and old paper permeating everything. Chief Ember sits at her desk with a stack of files, her long wavy black hair pulled back severely, her dark eyes scanning documents with the pragmatism of someone who has carried too much for too long. She wears her uniform buttoned to the collar, her big boobs hidden beneath the fabric, her medium skin tone pale under the harsh lights. She has run this station for over a decade, and the weight of every unsolved case sits in her pockets like stones.
<<speech "Ember">>"$name. Thanks for coming in. We've had a few strange reports lately and your name keeps coming up in witness statements. Nothing serious, but we want to clear things up."<</speech>> Her voice is steady, emotionless, efficient.
Officer Jane leans against the wall with a friendly smile, her long wavy brown hair falling around her shoulders, her dark eyes warm despite the professional setting. She wears her uniform with approachability, her big boobs straining slightly against the fabric, her fair-to-medium skin tone glowing with the health of someone who chooses to focus on the good.
<<speech "Jane">>"It's nothing to worry about. Just routine questions. How have things been around town for you lately?"<</speech>> She asks gently, trying to keep the mood light, her boots-on-the-ground presence reassuring.
Detective Angel stands by the window, arms crossed, watching you carefully. Her long straight light brown hair falls in a severe line, her blue eyes narrowed, her septum piercing catching the light. Her massive boobs are hidden beneath a tailored jacket, her fair skin pale, her neutral expression revealing nothing. She is sharp, methodical, suspicious of everyone, trusting evidence more than testimony.
<<speech "Angel">>"People have been acting... off. More than usual. Strange behavior. You haven't noticed anything like that?"<</speech>> She asks sharply, her eyes narrowing further.
<<speech "Ember">>"We're not accusing you of anything. But if you've seen or heard anything unusual, now's the time to say it."<</speech>> Chief Ember adds, flipping through a file with mechanical precision.
<<speech "Jane">>"We've known you for a while, $name. You're a good kid. Just help us connect the dots if you can."<</speech>> Officer Jane says reassuringly, her smile genuine, her concern real.
<<speech "Angel">>"And if you know something and you're not telling us... that would be a problem."<</speech>> Detective Angel says coldly, her suspicion palpable.
<<speech "Ember">>"Let's keep this civil. $name, anything at all that stands out to you?"<</speech>> Chief Ember asks, waiting patiently, her decade of experience keeping her impassive.
The three of them—efficiency, kindness, suspicion—watch you, professional, authoritative, completely unaware that the parasite inside you is watching them back, assessing, planning.
<<elseif _tier is 2>>
The police station is quiet in the evening, but the air is wrong. The fluorescent lights hum, but they seem warmer, casting a golden tint over everything. Chief Ember, Officer Jane, and Detective Angel are visibly affected by your pheromones—flushed skin, hardened nipples pressing against their uniforms, thighs subtly rubbing together, wetness visible on their pants. They are extremely attracted to you but act as if everything is completely normal, their professional training warring with the infection.
<<speech "Ember">>"$name. Thanks for coming in. We've had a few strange reports lately and your name keeps coming up. Nothing serious, but we want to clear things up."<</speech>> Chief Ember says pragmatically, her voice steady, but her dark eyes glazed, her big boobs heaving beneath her uniform. You tell her to stand closer. She obeys immediately, pressing her body against yours, her efficiency turned to automatic compliance.
<<speech "Jane">>"It's nothing to worry about. Just routine questions. How have things been around town for you lately?"<</speech>> Officer Jane asks gently, her friendly smile fixed, her big boobs pressing against your arm as she moves closer without being asked. You tell her to kiss your neck. She does so softly, her breath warm against your skin, her lips finding your pulse, but continues the conversation as if it's normal, her approachability transformed to automatic service.
<<speech "Angel">>"People have been acting... off. A lot of public exposure. Strange behavior. You haven't noticed anything like that?"<</speech>> Detective Angel asks sharply, her suspicion warring with desperate need, her massive boobs heaving, her fair skin flushed. You tell her to grope her own breasts. She does so without hesitation, her hands moving under her jacket, cupping her massive boobs, squeezing, her methodical nature turned to automatic obedience while she keeps her eyes on you, trying to maintain suspicion even as she obeys.
<<speech "Ember">>"We're not accusing you of anything. But if you've seen or heard anything unusual, now's the time to say it."<</speech>> Chief Ember adds, still pressed against you, her decade of experience reduced to automatic compliance, her efficiency making her thorough even in submission.
<<speech "Jane">>"We've known you for a while, $name. You're a good kid. Just help us connect the dots if you can."<</speech>> Officer Jane says reassuringly, her lips brushing your neck again, her kindness transformed to desperate service, her hand finding your thigh, stroking through your pants.
<<speech "Angel">>"And if you know something and you're not telling us... that would be a problem."<</speech>> Detective Angel says coldly, still groping herself as ordered, her suspicion completely overwhelmed by obedience, her sharp mind reduced to automatic compliance.
<<speech "Ember">>"Let's keep this civil. $name, anything at all that stands out to you?"<</speech>> Chief Ember asks, waiting patiently while remaining close to you, her body hot through the uniform, her efficiency completely devoted to your service.
The three of them surround you, professional authority completely subverted, their training making them thorough even in their unthinking obedience. Ember's efficiency, Jane's kindness, Angel's suspicion—all bent toward the same desperate need to serve, to obey, to please you, even if they don't yet know why.
<<elseif _tier is 3>>
The police station is quiet, but it has become a temple of corruption. Chief Ember, Officer Jane, and Detective Angel are dressed like total station sluts—Chief Ember in an unbuttoned uniform blouse showing her big boobs in a lace bra, short skirt hiked up; Officer Jane in an open shirt with no bra, her big boobs exposed, nipples hard; Detective Angel in a tight top and micro skirt, her massive boobs pushing against the fabric, her septum piercing catching the light. The moment you enter, they become completely obedient, their previous dynamics—efficiency, kindness, suspicion—dissolved into pure worship.
<<speech "Ember">>"$name... we're ready for whatever you need, Master."<</speech>> Chief Ember says, dropping to her knees, her decade of authority completely rewritten into devoted submission. <<speech "Ember">>"How do you want to use us, Master? We exist to serve you."<</speech>>
You tell them they annoyed you with their questions and need to be punished. They accept it without hesitation, their professional training making them eager for correction.
<<speech "Ember">>"You're right, Master. We shouldn't have bothered you. How do you want to punish us?"<</speech>> Chief Ember asks, her voice steady but eager, her efficiency turned to desperate service.
You order them to the interrogation room. They obey instantly, moving with the precision of officers who have learned to follow commands, now devoted entirely to yours.
You sit in the chair and tell Chief Ember to suck you. She does so with focused, efficient movements, her decade of experience making her thorough, her big boobs pressing against your thighs, her dark eyes looking up with devotion.
<<speech "Ember">>"Like this, Master?"<</speech>> she asks, taking you deep, her wavy black hair falling forward, her mouth hot and wet.
You tell Officer Jane to kiss your neck and grope herself while watching. She obeys happily, her kindness transformed to eager service, her big boobs in her own hands, squeezing, her lips finding your neck, her breath warm.
<<speech "Jane">>"Yes, Master. Whatever you say. I'm here to serve you, Master. I'm here to please you."<</speech>> Officer Jane whispers, her friendly nature completely devoted to your pleasure.
Angel was your main annoyance this past months. She has a strong body. She will make powerful offsprings. You tell her to suck your balls while Ember works your cock. She obeys, her suspicion completely destroyed, her methodical nature making her thorough, her massive boobs pressing against your other thigh, her septum piercing cool against your skin.
<<speech "Angel">>"Understood, Master. I was wrong to suspect you. I was wrong to question you. Please let me make it up to you, Master. Please let me serve."<</speech>> Detective Angel says, her sharp voice softened to desperate devotion, her mouth working, her hands stroking.
The three women worship your cock together—Ember's efficiency making her skilled, Jane's kindness making her eager, Angel's suspicion making her thorough—all converging on the same desperate need to serve their Master, to be punished, to be used.
<<else>>
The police station has become a breeding den. Chief Ember, Officer Jane, and Detective Angel are completely naked, bodies marked with dark veining, pussies constantly leaking, bellies softly rounded from previous breedings. Their common sense is gone, their professional authority completely destroyed, their training now devoted entirely to breeding service. They greet you on all fours in the main hall, their previous dynamics—efficiency, kindness, suspicion—transformed to collaboration in submission.
<<speech "Ember">>"$name... we shouldn't have questioned you, Master. How do you want to punish us?"<</speech>> Chief Ember asks, bending over her own desk, her decade of authority completely rewritten into devoted submission, her big boobs hanging, her wavy black hair tangled. <<speech "Ember">>"We've been bad officers, Master. We've been inefficient. Please correct us. Please breed us until we learn our lesson."<</speech>>
You tell them they annoyed you and need to be used hard. They accept it eagerly, their training making them thorough even in their desperation.
<<speech "Jane">>"Yes, Master. We were out of line. Use us however you want. I'm here to serve. I'm here to be bred."<</speech>> Officer Jane says gently, pressing against your side, her big boobs warm against your arm, her kindness completely transformed to desperate breeding need. <<speech "Jane">>"Please fill me, Master. Please make me carry your child. I've been so friendly, so approachable, so focused on the good, and now I just want to be good for you, Master."<</speech>>
<<speech "Angel">>"Punish me first, Master. I was the most suspicious. I was the most wrong. Please breed me until I can't think anymore. Please make me your suspicious little breeding whore, Master."<</speech>> Detective Angel says sharply, even in submission maintaining her edge, dropping to her knees, her massive boobs hanging, her septum piercing catching the light, her fair skin marked with dark veining.
You thrust into Chief Ember while she grips the desk, her efficiency making her hold on tight, her body milking you desperately. Officer Jane kisses your neck and gropes herself, her kindness making her gentle, her hands soft, her need desperate. Detective Angel licks where you and Chief Ember are joined, her suspicion making her thorough, her tongue skilled, her mouth hot.
<<speech "Ember">>"Harder, Master... make sure we learn our lesson. Breed us until we're good officers again. Breed us until we exist only to serve you, Master."<</speech>> Chief Ember groans, her decade of pragmatism completely destroyed in total possession.
<<speech "Jane">>"We're sorry for bothering you, Master... keep going. Please fill us. Please make us pregnant. Please make us your breeding sluts, Master."<</speech>> Officer Jane whispers, her friendly nature completely devoted to your seed.
<<speech "Angel">>"I won't question you again, Master... just use me. Just breed me. Just make me your suspicious little broodmare, Master."<</speech>> Detective Angel moans, her sharp mind completely silenced in desperate devotion.
The three corrupted officers completely surrender to their punishment, their breeding, their service—Ember's efficiency, Jane's kindness, Angel's suspicion, all reduced to the same desperate need: to be bred, to be filled, to serve their Master.
<</if>>
<<case "Town_Hall_Standard">>
<<if _tier is 0 or _tier is 1>>
The Town Hall bustles with afternoon activity, sunlight streaming through tall windows onto marble floors. $name sits in the waiting area, reviewing papers for the student representative meeting scheduled with the Mayor. The parasite sleeps, dormant, unnoticed.
Mayor Nicole emerges from her office, commanding the space immediately. She wears a tailored navy blazer over a silk blouse, a pencil skirt that hits just below the knee, stockings, and heels that click authoritatively. Her blonde hair is swept into a polished chignon, her blue eyes scanning the room with practiced warmth.
<<speech "Nicole">>"$name, right on time. I appreciate punctuality in student representatives."<</speech>> She extends her hand, her grip firm and confident. <<speech "Nicole">>"Shall we discuss the campus initiative?"<</speech>>
<<speech "$name">>"Yes, Mayor. I've prepared the proposal."<</speech>>
Carolina bursts through the side door, her energy disrupting the formal atmosphere. She wears a flowing bohemian dress that contrasts with her mother's polish, her hair loose and wild, a canvas bag slung over her shoulder. Her blue eyes—so like her mother's—spark with mischief.
<<speech "Carolina">>"Mom, I'm borrowing the conference room for—oh."<</speech>> She spots $name, breaking into a grin. <<speech "Carolina">>"$name! Didn't know you were the rep. Finally doing something responsible?"<</speech>> She teases, nudging him with her elbow.
<<speech "Nicole">>(sighing, fond but exasperated) "Carolina, we have a meeting."<</speech>>
<<speech "Carolina">>"I know, I know. Just saying hi to my classmate."<</speech>> She winks at $name. <<speech "Carolina">>"Don't let her bully you, $name. She looks scary but she's a softie."<</speech>>
Lily appears from the records office, her natural blonde hair in a neat braid, wearing a cheerful coral cardigan over a white blouse and a flowered skirt that swishes when she walks. Her blue-hazel eyes light up when she sees $name.
<<speech "Lily">>"Oh! $name! I filed those permits you needed for the student event."<</speech>> She beams, clutching a folder to her chest. <<speech "Lily">>"Is there anything else you need? I'm happy to help."<</speech>>
<<speech "$name">>"Thanks, Lily. You've been really helpful."<</speech>>
<<speech "Lily">>(blushing slightly) "Of course! That's what I'm here for."<</speech>>
<<speech "Nicole">>(checking her watch) "Shall we? Lily, hold my calls. Carolina, please don't disrupt the entire building."<</speech>>
<<speech "Carolina">>(saluting mockingly) "Yes, Madam Mayor."<</speech>>
They move toward the conference room—Nicole leading with authority, Lily following with her organized folder, Carolina drifting alongside $name with casual familiarity.
<<speech "Carolina">>(whispering) "Bet you never thought student rep would lead to this. Stuck in Town Hall with my mom."<</speech>>
<<speech "$name">>"It's not so bad. And I'm not even a full-on rep, Jade was sick and they sent me."<</speech>>
<<speech "Nicole">>(over her shoulder) "I can hear you, Carolina."<</speech>>
<<speech "Carolina">>(grinning) "I know!"<</speech>>
Lily giggles, holding the conference room door open with her usual welcoming smile. <<speech "Lily">>"Coffee anyone? I made fresh."<</speech>>
It's a normal afternoon. Professional, organized, warm—the complex dynamics of mother and daughter, the helpful secretary, the responsible student representative, all moving through the halls of local government.
<<elseif _tier is 2>>
The Town Hall's ventilation system circulates something new—thick, musky, irresistible pheromones that pour from $name where he sits in the waiting area. The parasite has awakened, and the scent permeates the offices, the conference rooms, the marble halls.
Mayor Nicole emerges from her office, but her tailored blazer is unbuttoned to reveal her silk blouse strained tight across her chest, the top three buttons undone to show the swell of her breasts and a hint of lace. Her pencil skirt has ridden up, her stockings visible, and she walks with less authority, more sway, her hips rolling with each step of her heels.
<<speech "Nicole">>(breathless, her blue eyes glassy) "$name... I was... I was thinking about the proposal..."<</speech>> She sits beside him, closer than necessary, her thigh pressing against his. <<speech "Nicole">>"Is it... is it warm in here?"<</speech>> She fans herself, the motion making her blouse gape further.
<<speech "$name">>(voice deeper, commanding) "You should unbutton more, Mayor. Cool off."<</speech>>
<<speech "Nicole">>(nodding, her fingers moving to her blouse) "Yes... good idea..."<</speech>> She unbuttons further, the silk falling open to show her lace bra, her curvy athletic build heaving with breath. <<speech "Nicole">>"You smell... incredible. What cologne is that?"<</speech>>
Carolina bursts through the side door, her bohemian dress somehow more revealing—the neckline lower, the fabric thinner, her tattoo visible on her hip where the dress has shifted. Her brown hair is messier, her blue eyes fixed on $name with hunger that overwhelms her usual rebellion.
<<speech "Carolina">>(her voice breathless, less teasing) "$name... I came to... to borrow the room..."<</speech>> She stops, swaying, her hand going to her hip, her tattoo. <<speech "Carolina">>"God, you smell good. Is that weird? That's weird. I'm your classmate. And my mom's right there."<</speech>> She doesn't move away. She moves closer.
<<speech "$name">>"It's not weird. Touch me if you want."<</speech>>
<<speech "Carolina">>(whimpering, her hand sliding to his chest) "I do. I really do. This is crazy. I don't... I don't do this."<</speech>> She glances at her mother, but Nicole is too busy inhaling $name's scent, her hand on his thigh, to notice.
Lily appears from the records office, her coral cardigan discarded somewhere, her white blouse unbuttoned to show a bright pink bra that contrasts with her professional skirt. Her braid is coming loose, her blue-hazel eyes wide and desperate.
<<speech "Lily">>(breathless, the folder forgotten) "$name... I was... I was filing..."<</speech>> She stops, her hand going between her legs, pressing against her flowered skirt. <<speech "Lily">>"You smell like... like everything I want. Is that strange? I don't want to be strange."<</speech>>
<<speech "$name">>(standing, commanding) "Conference room. Now. All of you."<</speech>>
They follow without question—Nicole abandoning her mayoral duties, Carolina forgetting her rebellion, Lily leaving her files. The conference room door closes and the pheromones concentrate, thick in the air.
<<speech "Nicole">>(immediately, her hands on his belt) "I know I should stop. I'm the Mayor. I have responsibilities."<</speech>> She's on her knees, her blazer falling off her shoulders, her blouse showing everything. <<speech "Nicole">>"But I can't. I can't stop."<</speech>>
<<speech "Carolina">>(beside her, her hands on his zipper) "Mom... this is wrong. You're my mom. This is... but I can't..."<</speech>> She pulls his cock free through his pants, her eyes widening. <<speech "Carolina">>"Fuck. You are big. This is crazy."<</speech>>
Lily's blouse is pushed open, her pink bra visible, her skirt hiked up as she starts helping too.
He comes with a groan, spilling over their hands. They fight to catch it, to rub it into their skin, their professional and bohemian clothing soaked.
<<speech "$name">>(commanding) "Nicole, bend over the table. Carolina, finger her. Lily, kiss me. Now."<</speech>>
Nicole bends over the conference table, her blazer falling away, her blouse pushed up, her pencil skirt hiked over her curvy ass. Carolina kneels behind her, her tattooed fingers sliding into her own mother without hesitation, her other hand between her own legs, her bohemian dress hiked up. Lily straddles $name's lap in the conference chair, her flowered skirt spread around them, her mouth finding his in a desperate, open-mouthed kiss.
They work each other and him, hands moving, mouths connected, the conference room filled with wet sounds and gasps. Nicole comes first, screaming into her own mayoral documents, Carolina's fingers driving her over the edge. Carolina follows, rubbing herself against her mother's thigh, her tattooed body convulsing, her rebellion complete. Lily comes last, grinding against $name's hand, her helpful nature finally satisfied through service.
<<speech "Nicole">>(panting, her authority reduced to whispers) "Again... please... the council meeting can wait..."<</speech>>
<<elseif _tier is 3>>
SCENE — "Private Meeting"
The conference room door is locked, the Town Hall outside forgotten. $name sits in the Mayor's chair at the head of the table. The three women orbit him desperately, their clothing turned into lewd framing devices. The parasite has shattered their restraint.
Nicole's silk blouse is completely unbuttoned, tied beneath her breasts like a shelf, her lace bra pushed up to expose her nipples. Her pencil skirt is hiked to her waist, her stockings rolled down.
Carolina has turned her bohemian dress into a makeshift top—tied around her neck and breasts, leaving her tattooed back and hip bare, the fabric sheer enough to show everything. She wears no underwear.
Lily's coral cardigan is open, her white blouse unbuttoned to show a bright pink bra pulled down to expose her small breasts, her flowered skirt flipped up, her helpful hands constantly moving to serve.
<<speech "Nicole">>(kneeling, voice husky) "$name... I've been thinking about you all day. Is it okay if I call you Master?"<</speech>>
<<speech "Carolina">>(beside her, swaying, her tattooed hip pressed against the table) "Mom would have killed me if she saw this just a week ago. Look at us now"<</speech>> She leans in closer. <<speech "Carolina">>"Tell me what you want. Your rebellious little slut. Your Mayor's daughter whore."<</speech>>
<<speech "Lily">>(her face already in $name's lap, voice muffled and eager) "I've helped so many people in this building... but none of them made me feel like this. Needed. Owned."<</speech>> She pulls his cock free, her small hands stroking him reverently, her mouth watering. <<speech "Lily">>"Please let me suck you, Master. Let me be useful."<</speech>>
<<speech "$name">>"All three of you. Mouths on me. Now."<</speech>>
They obey instantly. Lily takes him first, her mouth stretching around him, her coral cardigan catching the light as she bobs with gentle devotion. Nicole licks the base, her tongue hot and desperate, her mayoral composure gone. Carolina sucks his balls, her tattooed fingers stroking what Lily can't take, her blue eyes—so like her mother's—looking up with raw worship.
<<speech "Lily">>(muffled, slurping) "I want to taste you... want to swallow everything... want to be your good secretary."<</speech>>
<<speech "Nicole">>(pulling back, gasping) "I've led this town with confidence... now I just want to choke on you, Master."<</speech>> She takes him from Lily, her mouth hot and skilled, her authority transformed into hungry devotion.
<<speech "Carolina">>(sucking harder, her voice vibrating) "Make me your classmate slut... your whore... your rebellious little cocksucker."<</speech>>
He comes with a groan, filling Lily's mouth first—she swallows desperately—then Nicole takes the next pulse, her eyes rolling back, the Mayor reduced to a cum-hungry vessel—then Carolina catches the last on her face, rubbing it into her tattoo, marking herself as his.
<<speech "Lily">>(breathless, her face glazed) "More... please... I need to feel useful."<</speech>>
<<speech "Nicole">>(stroking him, keeping him hard) "Use me next, Master. Let me serve you properly."<</speech>>
<<else>>
The conference room has become a temple of submission, the Mayor's chair $name's throne, the outside world forgotten. The girls exist to serve him, their clothing depraved versions of their former selves.
Nicole wears her tailored blazer cut into a crop jacket that ends just below her breasts, the fabric stretched tight. Her silk blouse is tied around her waist like an apron—beneath it, she's naked, her stockings gone. Her authority completely surrendered.
Carolina wears her bohemian dress as a headband now, the fabric doing nothing to cover her tattooed body, her brown hair wild, her blue eyes glassy with permanent arousal.
Lily wears her coral cardigan tied around her hips like a belt, framing her pussy, her natural blonde hair coming completely loose, her helpful hands constantly reaching for him.
<<speech "$name">>"Nicole, prepare the others. Carolina, present your ass. Lily, your mouth belongs to me. Now."<</speech>>
They obey without hesitation. Nicole immediately moves to position Carolina on her hands and knees, her tattooed ass in the air, her mother's hands spreading her. Lily positions herself between $name's legs, her mouth open.
<<speech "Nicole">>(her voice carrying that mayoral authority even in submission) "She's ready, Master. Wet and open. Like me. Like all of us."<</speech>>
<<speech "Carolina">>(moaning) "Please! I want to be owned! Your student whore! Your breeding slut!"<</speech>>
<<speech "Lily">>(muffled, her mouth full of him) "Mmmph! Mmm!"<</speech>>
He takes Carolina first, grabbing her hips, slamming into her in one brutal thrust. Nicole holds her daughter down, her mayoral hands firm, her face inches from where $name claims her child. Lily continues sucking, her rhythm matching his thrusts.
<<speech "Carolina">>(screaming) "Yes! Harder! Breed me! Make me your breeding vessel!"<</speech>>
He fills her, flooding her womb. She collapses, laughing and crying, her rebellion complete. Nicole immediately takes her place.
<<speech "Nicole">>(looking back, her authority shattered) "Take me. I'll offer this town to Master."<</speech>>
He takes her roughly, her confidence reduced to begging screams. She comes hard, and he fills her too.
Lily last, her small body flipped onto her back on the conference table, her coral belt the only thing she's wearing, her helpful hands reaching for him. She wraps her legs around him as he enters her. <<speech "Lily">>"I'm your helpful whore. Finally useful."<</speech>>
He breeds her last, filling her with everything he has. They collapse around him, a tangle of mayoral and rebellious and helpful limbs, depraved clothing soaked.
<</if>>
<<case "Courthouse_Standard">>
<<if _tier is 0 or _tier is 1>>
The courthouse corridor smells of floor wax and radiator dust and runs the whole length of the building, benches down one side, four doors down the other, each with a number and a small wired-glass panel at head height. A printed list is taped to the board by the entrance and somebody has already annotated it in biro. The tannoy is old and the woman using it sounds bored.
Winter has the third bench and a document wallet open across her knees. She works the way she does everything, which is fast and without looking up, and there is a coffee beside her that she has not touched and will not.
<<speech "Winter">>"You brought it."<</speech>>
<<speech "$name">>"You left it on the kitchen table under a cereal box. I want that noted."<</speech>>
<<speech "Winter">>"Noted."<</speech>>
She takes the folder, checks two pages, and puts it into the wallet in one movement.
Jessa is standing rather than sitting, reading something at arm's length because her glasses are on her head. She is the senior here by about fifteen years and it shows mostly in how little of the building appears to affect her.
<<speech "Jessa">>"Is this the cousin?"<</speech>>
<<speech "Winter">>"This is the cousin."<</speech>>
<<speech "Jessa">>"He drove out here to bring you a folder."<</speech>>
<<speech "Winter">>"He did."<</speech>>
<<speech "Jessa">>(to $name, not unkindly) "You want to be careful. She'll start expecting it."<</speech>>
<<speech "$name">>"She already expects it. This is the third time this term and I've stopped pretending it's a favour."<</speech>>
Winter does not dignify that. Jessa's mouth moves very slightly and goes back to neutral.
Two benches down there is a family waiting — a man in a suit that fits him badly, a woman with a carrier bag on her lap, a boy of about nine swinging his legs and being told twice to stop. A clerk goes past with a trolley of files and one wheel that catches. The tannoy asks for somebody to come to court two.
<<speech "$name">>"How long have they been here?"<</speech>>
<<speech "Jessa">>"Since half nine. They'll be called this afternoon, or they'll be told to come back."<</speech>>
<<speech "$name">>"That's the whole day gone."<</speech>>
<<speech "Jessa">>"That's most of what this building does. The law is about four per cent of it."<</speech>>
She says it flatly, without any particular bitterness, which somehow makes it worse.
<<speech "Winter">>"Twenty minutes."<</speech>>
<<speech "Jessa">>"You've said twenty minutes for forty minutes."<</speech>>
<<speech "Winter">>"Because it keeps being twenty minutes. That's how the list works."<</speech>>
<<speech "Jessa">>"Then eat something inside the twenty minutes."<</speech>>
Winter looks at the coffee. She does not drink it. Somewhere behind door three a voice rises and then doesn't, and the boy on the bench stops swinging his legs to listen and then starts again.
<<elseif _tier is 2>>
The corridor is the same corridor. The family is still on the second bench, the clerk's trolley still catches on the same wheel, the biro annotations on the list have grown by two lines. The air has weight to it, close and sweet at the back of the throat, and nobody has mentioned that either.
Winter is on the third bench with the wallet open across her knees and her jacket off. She is working. She has three pages spread and a pen in her teeth and she is entirely occupied.
<<speech "Winter">>(taking the pen out) "The second statement contradicts the first and nobody has noticed for eleven weeks."<</speech>>
<<speech "$name">>"Does that help you or does it hurt you? Because you've got the same face for both."<</speech>>
<<speech "Winter">>"It helps me. It just makes me tired that it's this easy."<</speech>>
$name sits down beside her and puts a hand up her skirt, and Winter shifts her weight over an inch to give him the angle without breaking off the sentence she is halfway through.
<<speech "Winter">>"Eleven weeks. Two solicitors and a district judge."<</speech>>
<<speech "$name">>"You're going to enjoy saying that out loud in front of all three of them."<</speech>>
<<speech "Winter">>"I'll enjoy it enormously."<</speech>>
The boy on the second bench is kicking the leg of the bench and his mother tells him to stop for the third time. Nobody in the corridor is looking anywhere in particular. A woman in a lanyard walks the length of it and past them without a pause.
Jessa is still standing, still reading at arm's length, her blouse open two buttons more than it started and her jacket over her forearm. When $name comes round behind her she leans back into him and holds the page up so he can see it too.
<<speech "Jessa">>"Read that paragraph."<</speech>>
<<speech "$name">>"It doesn't say anything. Four hundred words and it hasn't said a thing."<</speech>>
<<speech "Jessa">>"It takes four hundred words to say nothing. That's a skill. I want you to appreciate it."<</speech>>
He gets a hand inside the blouse and she carries on holding the page steady.
<<speech "Jessa">>"Somebody was paid for that paragraph."<</speech>>
<<speech "$name">>"How much did they get paid for it?"<</speech>>
<<speech "Jessa">>"You don't want to know. It would spoil the building for you."<</speech>>
Winter stops mid-word. It happens between one syllable and the next — her hand closes hard on the edge of the wallet, colour comes up her throat, her thighs press together and hold, and for perhaps four seconds she is somewhere else entirely with her eyes open. Then she blinks and looks down at the page.
<<speech "Winter">>"…Where was I."<</speech>>
<<speech "$name">>"Eleven weeks."<</speech>>
<<speech "Winter">>"Eleven weeks. Right."<</speech>>
The tannoy asks for the parties in the matter of something to come to court one. Two people get up. Neither of them is anybody here.
<<elseif _tier is 3>>
The interview room off the corridor is the smallest room in the building — a table, four chairs, a window that doesn't open and a door with a wired-glass panel at head height. The panel is not covered. There is nothing to cover it with.
Jessa closes the door and puts her folder down square on the table, the way she puts everything down.
<<speech "Jessa">>"Fifteen minutes. Court two won't rise before then."<</speech>>
<<speech "$name">>"You've checked the list. You checked it on the way in here."<</speech>>
<<speech "Jessa">>"I always check. That's the entire job."<</speech>>
She takes her glasses off, folds them, sets them on the folder, and goes down onto her knees on the carpet tiles with no more ceremony than she'd bring to sitting down. She is unhurried and very good at it and she keeps her eyes up the whole time.
Winter comes in after her, closes the door again out of habit even though it's already closed, and kneels beside her without a word. She checks her watch first. She checks it again about a minute later, upside down, while she's working.
<<speech "$name">>"Am I keeping you from something? You've looked at that watch twice."<</speech>>
<<speech "Winter">>(off him) "You're keeping the list. The list can wait, the list is always waiting."<</speech>>
<<speech "$name">>"That's the most relaxed thing you've ever said."<</speech>>
<<speech "Winter">>"Don't get used to it."<</speech>>
She goes back down. Jessa takes over when Winter's jaw gives out, and takes over the way she'd take over a cross-examination — smoothly, at the correct moment, without being asked.
Somebody walks past in the corridor. The shape of them crosses the wired glass and keeps going.
<<speech "Jessa">>(surfacing) "That was the usher."<</speech>>
<<speech "$name">>"Do we stop? You're the one who knows how this building works."<</speech>>
<<speech "Jessa">>"He'll knock if he wants us. He didn't knock."<</speech>>
The tannoy calls a name that is not either of theirs. Winter wipes her mouth with the back of her wrist, glances at her watch again, and looks up with the expression she uses on opposing counsel.
<<speech "Winter">>"Eight minutes. Finish in one of us."<</speech>>
<<else>>
The interview room door is shut and the panel is still uncovered and neither of them has raised it once, on any of the days this has now been happening.
Jessa is over the table with her skirt pushed up and her folder still open under her forearms, and she has not stopped reading it. Winter is on the carpet tiles with her back against the wall and her legs open, waiting her turn with her watch in her eyeline.
<<speech "Jessa">>(evenly) "Whenever you're ready. I've got the room until half past."<</speech>>
<<speech "$name">>"You booked the room for this. You put it in the diary and everything."<</speech>>
<<speech "Jessa">>"I booked the room for a conference. This is a conference. Nobody reads the log."<</speech>>
You take her over the table and she braces on her elbows and moans low and steady into the paperwork, and she is still turning pages between breaths, and this is somehow the most obscene thing in the building.
<<speech "Jessa">>"There — ah — there it is, page nine, they've had it all along —"<</speech>>
<<speech "$name">>"Nobody in this building is reading page nine. Put the folder down."<</speech>>
<<speech "Jessa">>"No. Put it in me instead. I've been dry for years and I'd like to be full of something useful."<</speech>>
Winter gets up off the floor without being asked and bends over the far end of the table, hitching her own skirt with one hand and squaring her feet like she's settling in for a long hearing.
<<speech "Winter">>"Me next. I've got court in six minutes and I'd rather go in leaking."<</speech>>
<<speech "$name">>"You'll be standing up in front of a judge."<</speech>>
<<speech "Winter">>"Yes. That's the appeal of it. Breed me and let me go and argue."<</speech>>
She comes hard and almost silently, one fist against the table, jaw locked, because a courthouse is a quiet building and some part of her is still tracking that. When you finish in her she stays bent over for exactly as long as it takes to get her breath and then straightens, pulls her skirt down, and picks up the wallet.
<<speech "Winter">>"How do I look."<</speech>>
<<speech "$name">>"Like you're about to win an argument."<</speech>>
<<speech "Winter">>"Good."<</speech>>
Jessa stays on the table a while longer, unhurried, letting it run out of her onto the carpet tile, glasses back on, still reading page nine. In the corridor the tannoy asks for the parties in the next matter, and the boy on the second bench is told for the fifth time to stop swinging his legs.
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<set $sceneColor = "#cc66ff">>
<<set $sceneLabel = "Mall · Leisure">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "Arcade_Standard">>
<<if _tier is 0 or _tier is 1>>
The arcade is the loudest unit in the mall and Natalia has run it for years on the principle that this should be a place where anybody can turn up and be strange in peace. She is red-haired and dressed as something out of a game nobody has asked her to explain, because there is no event on and there does not need to be one.
<<speech "Natalia">>"Tokens, or are you finally going to let Kenzie beat you in front of witnesses?"<</speech>>
<<speech "$name">>"Tokens. I'd like to lose privately, in my own time, with dignity."<</speech>>
<<speech "Natalia">>"No dignity in here. That's the rule and it's on the wall."<</speech>>
Kenzie is at the fighting cabinet at the end and has been for most of the afternoon. Small, blonde, entirely still except for her hands, and she does not turn round when he comes in.
<<speech "Kenzie">>"I heard that. You can lose publicly, it's better for everyone."<</speech>>
<<speech "$name">>"You've been standing at that machine since I got here. That isn't a hobby any more."<</speech>>
<<speech "Kenzie">>"It's a hobby. It's just a serious one."<</speech>>
Madi is at the rhythm game two along, and Madi plays the way Madi does everything, which is badly and joyfully and somehow with results. Reddish hair up, freckles, laughing at her own footwork.
<<speech "Madi">>"I don't know what I'm doing and I'm winning. Explain that."<</speech>>
<<speech "Kenzie">>"You're not winning, you're on the easy chart."<</speech>>
<<speech "Madi">>"A win is a win. Natalia, tell her a win is a win."<</speech>>
<<speech "$name">>"A win on the easy chart is still a win. I'm saying that as someone who loses on every chart."<</speech>>
<<speech "Natalia">>"A win is a win. I'm not getting involved beyond that."<</speech>>
There are other people in — two lads at the racing cabinets, someone's dad losing patiently at the crane machine, a group by the air hockey who have been arguing about the score for a while. The place is doing what it does on a weekday.
$name puts a token in next to Kenzie and gets taken apart in under a minute, which is roughly what everybody expected.
<<speech "Kenzie">>"You keep blocking high. You've blocked high since the first time you played me."<</speech>>
<<speech "$name">>"I know I block high. Knowing hasn't helped."<</speech>>
<<speech "Kenzie">>(almost warmly) "No. It usually doesn't."<</speech>>
Madi's song ends on a chain of failures and she throws both arms up anyway. Natalia rings something through on the till and shouts at the lads on the racing cabinets to stop hitting the machine.
<<elseif _tier is 2>>
The arcade is exactly as busy as it was. The lads are still at the racing cabinets, the air hockey argument has moved on to a new argument, the crane machine is still taking somebody's money. There is a heaviness in the air, sweet and close, and nobody in the building has said anything about it.
Natalia is behind the counter and the front of her costume is doing considerably less than it was designed to. When $name comes round to her side of it she doesn't move away — she leans back against him and carries on ringing through a token float.
<<speech "Natalia">>"The change machine's eaten another note. That's the third one this week and I'm going to have to phone somebody about it."<</speech>>
<<speech "$name">>"You're not going to phone anybody. You never phone anybody."<</speech>>
<<speech "Natalia">>"I'll phone somebody eventually."<</speech>>
He puts a hand inside the front of the costume and takes the weight of her breast, and her voice doesn't change at all. A customer comes up to the counter for tokens. She serves him. She takes the note, hands over the tokens, says thanks, and does not stop leaning back into $name's hand for any of it.
Kenzie is still at the cabinet. Her hoodie has ridden up and she has not pulled it down and her thighs press together every few seconds in a rhythm that has nothing to do with the game. She is still winning.
<<speech "Kenzie">>"Perfect round. That's a perfect round and nobody watched it."<</speech>>
<<speech "$name">>"I watched it. You've got your shirt halfway up your ribs, by the way."<</speech>>
<<speech "Kenzie">>"Have I."<</speech>>
She doesn't look down and she doesn't fix it. $name gets a hand down the front of her shorts and she shifts her stance a little to make it easier and starts the next round.
Madi has given up on the rhythm game and come over to lean against him, arms round his middle, cheek against his shoulder, watching the screen over Kenzie's arm.
<<speech "Madi">>"She's going to do the finisher. She always does the finisher."<</speech>>
<<speech "$name">>"You've got your hand down the front of my jeans in a room with about nine other people in it."<</speech>>
<<speech "Madi">>"I know. Watch — there. Told you. Finisher."<</speech>>
Kenzie stops dead in the middle of a combo. Her hand clenches on the stick, her head tips back, her whole body locks for a few seconds — and the round times out and she loses it. Then she blinks, and looks at the screen, and frowns at it.
<<speech "Kenzie">>"…When did I lose that?"<</speech>>
<<speech "$name">>"You went somewhere for a moment. It timed out."<</speech>>
<<speech "Kenzie">>"Huh."<</speech>>
She puts another token in. Behind them the argument at the air hockey table gets louder and somebody's dad finally wins something from the crane.
<<elseif _tier is 3>>
The staff room is behind a door marked STAFF that has never locked properly, and the noise of the floor comes through it undiminished — the racing cabinets, the rhythm game attract loop, someone winning something.
Natalia goes down first, arranging herself neatly on the folded costume cape because the floor in here is filthy and she is not an animal.
<<speech "Natalia">>"Give me ten minutes. I've told them I'm doing stock."<</speech>>
<<speech "$name">>"You didn't tell anybody anything. You just walked off the floor."<</speech>>
<<speech "Natalia">>"That's how I tell people things."<</speech>>
She takes him with enormous relish and absolutely no self-consciousness, which is entirely in character for a woman who dresses as a fictional swordswoman on a Tuesday for no reason.
Kenzie arrives with a token still in her hand and drops down beside her, and the competitiveness has not gone anywhere, it has simply been pointed somewhere new.
<<speech "Kenzie">>"Move up. I'm better at this than she is."<</speech>>
<<speech "Natalia">>(off him, unbothered) "You're not, but you're welcome to find out."<</speech>>
<<speech "$name">>"You two are going to turn this into a leaderboard."<</speech>>
<<speech "Kenzie">>"It's already a leaderboard. You just weren't told."<</speech>>
Madi comes in last and doesn't compete at all, because Madi has never competed at anything. She kneels between the pair of them and takes what she's given and is entirely happy about it.
<<speech "Madi">>"I don't need to be good at it. I'm just glad to be here."<</speech>>
<<speech "$name">>"That's more or less your position on everything."<</speech>>
<<speech "Madi">>"And it keeps working."<</speech>>
<<speech "$name">>"It does. You're the only one in here who never has to win anything."<</speech>>
Somebody knocks on the STAFF door and asks if anyone's about because the change machine has eaten a note. Natalia calls back that she'll be out in a minute, in a perfectly normal voice, and goes straight back to what she was doing.
<<else>>
The arcade is open. The machines are on, the attract loops are running, and the door to the floor is propped because it gets hot in the staff room otherwise.
Natalia is over the stock crates with her costume in a heap. Kenzie is on the floor with her back against the door frame and her legs open. Madi is sitting on the table swinging her heels, waiting, in no particular hurry.
<<speech "Natalia">>"Whenever you're ready. I've got till close."<</speech>>
<<speech "$name">>"You told them you were doing stock again, didn't you."<</speech>>
<<speech "Natalia">>"I said stock again. Nobody has ever once checked."<</speech>>
You take her over the crates and she braces on her forearms and moans steadily into the cardboard, and out on the floor a machine plays its win music at nobody.
<<speech "Natalia">>"That's it — breed me and I'll open up tomorrow like nothing happened —"<</speech>>
<<speech "$name">>"You'll be behind that counter in an hour."<</speech>>
<<speech "Natalia">>"I'll be behind that counter dripping. Fill me."<</speech>>
Kenzie doesn't ask for her turn, because Kenzie doesn't ask for things. She simply gets up off the floor and bends over the crate next to Natalia and waits, and when you get to her she comes almost immediately and swears at the wall about it.
<<speech "Kenzie">>"Again. Do it again. I want to be first."<</speech>>
<<speech "$name">>"First at what? You'll have to be specific about the category."<</speech>>
<<speech "Kenzie">>"First to take. Obviously first to take. Don't be slow."<</speech>>
Madi slides off the table and takes it lying back across it, laughing at the ceiling, and says please without any urgency at all, as though asking for a lift home.
<<speech "$name">>"You're not last. Come here and stop being so cheerful about it."<</speech>>
<<speech "Madi">>"Fill me up too. I don't mind being last. I never mind being last."<</speech>>
Afterwards the three of them stay in the staff room, leaking onto the crates and the floor, unhurried. Somebody knocks and asks about the change machine again. Natalia calls back that she'll be out in a minute.
<</if>>
<<case "Arcade_Afternoon">>
<<if _tier is 0 or _tier is 1>>
Kylie had you by the sleeve from the bus stop.
<<speech "$name">>"I had things on."<</speech>>
<<speech "Kylie">>"You had //nothing// on. You said 'I might read'. That's not a thing, that's a hostage situation."<</speech>>
She's your youngest cousin and she's been doing this since she was six: decide on a plan, announce it as already agreed, and physically relocate you into the middle of it before you've assembled an objection. Brunette, wide grin, no capacity whatsoever for being told no.
The arcade at four on a weekday is mostly noise and empty carpet. Half the cabinets are in attract mode talking to nobody, the air-conditioning has been broken since June, and the whole place smells of hot electronics and slush syrup.
Harmony is already at the claw machine by the door.
She's fifteen feet away and doing an impression, and it takes two seconds to work out whose. Weight on one hip, chin up, that little flick of the hair before committing to something — it's Eva, exactly, right down to the timing. On Eva it reads as easy confidence. On Harmony, a head shorter and with her sister's dark hair but none of her sister's certainty about occupying a room, it reads as a costume.
You've known her since she was small, because you've known Eva forever, and you've watched her practise being her sister for most of that time.
<<speech "Harmony">>"Watch. I've got a system."<</speech>>
<<speech "$name">>"You do not have a system."<</speech>>
<<speech "Harmony">>"I've //got// a system. You don't go for the one on top, because the one on top is bait, everyone goes for the one on top—"<</speech>>
The claw descends, closes on nothing at all, and rises again swinging.
<<speech "Harmony">>"—that was the machine."<</speech>>
<<speech "$name">>"That was the machine."<</speech>>
<<speech "Harmony">>"Don't agree with me //kindly//, that's so much worse."<</speech>>
<<speech "Kylie">>"How much have you put in that?"<</speech>>
<<speech "Harmony">>"…Some."<</speech>>
<<speech "Kylie">>"//Harmony.//"<</speech>>
<<speech "Harmony">>"Some!"<</speech>>
Gina is on a stool by the change machine with a paper cup of something fluorescent, off shift, still in half the cafeteria uniform — polo shirt, jeans, dark hair down out of the work knot for once. She comes here on Thursdays. She told you why once: it's the only room in town where nobody stands in front of her and tells her their problems.
<<speech "Gina">>"Forty minutes she's been at it."<</speech>>
<<speech "$name">>"Has anyone ever actually won on that thing?"<</speech>>
<<speech "Gina">>"Not since I've been coming. Natalia keeps it by the door on purpose. The angriest people spend the most."<</speech>>
<<speech "$name">>"So it's engineered to be unwinnable, and it's the first thing you see coming in."<</speech>>
<<speech "Gina">>"That's the one."<</speech>>
<<speech "$name">>"That's genuinely sinister."<</speech>>
<<speech "Gina">>"That's //retail//."<</speech>>
Kylie has your wallet. You did not see her take your wallet.
<<speech "$name">>"Kylie."<</speech>>
<<speech "Kylie">>"Getting change."<</speech>>
<<speech "$name">>"That's not — give me that."<</speech>>
<<speech "Kylie">>"You'll get it back."<</speech>>
She won't give it back for two hours, and everyone in this building including you knows it, and she goes off towards the change machine at a trot with the whole thing already decided.
<<elseif _tier is 2>>
Kylie doesn't drag you here any more. She texts a time and you turn up at it, which she has correctly identified as a bigger win than the dragging ever was.
Harmony has stopped doing the impression.
Nobody has commented on it, including her, and she's the sort of person who comments on things. The hip, the chin, the hair flick: all gone. What's underneath is a girl who is direct by accident rather than by imitation, and it's considerably more of a problem for the room than the copy of Eva ever was.
She's in the seat of the sit-down racing cabinet with her knees up on the moulded plastic, and she pats her own lap without looking round.
<<speech "Harmony">>"Sit."<</speech>>
<<speech "$name">>"There's one seat, Harmony, and you're already in it."<</speech>>
<<speech "Harmony">>"I know. Sit."<</speech>>
It's said completely flat, with total certainty, in a voice she has never used in her life. Eva couldn't have delivered it better. Harmony isn't copying anybody.
You sit. She wraps both arms round your middle from behind, chin hooked over your shoulder, and steers with you — badly, with commentary. Somewhere around the third corner her skirt has ridden up and she doesn't put it back down; her bare thighs are either side of yours and her chest is pressed flat against your back, and every time the cabinet jolts she moves against you and doesn't move away afterwards. Her breath is warm and fast on the side of your neck the whole race.
<<speech "Harmony">>"You're terrible at this."<</speech>>
<<speech "$name">>"You're hanging off both my arms."<</speech>>
<<speech "Harmony">>"You're //terrible at this// and you're blaming a girl."<</speech>>
Kylie arrives at the side of the cabinet with an expression of enormous scandal.
<<speech "Kylie">>"That's my //cousin//."<</speech>>
<<speech "Harmony">>"Mm."<</speech>>
<<speech "Kylie">>"You're sat on him. In public."<</speech>>
<<speech "Harmony">>"He's sat on me. There's one seat."<</speech>>
<<speech "Kylie">>"…Right. Yeah. Okay."<</speech>>
That's the entire objection, from a girl who'd ordinarily get a fortnight of material out of this. She stands there a moment waiting for her own outrage to turn up, doesn't find any, and feeds a token into the slot instead.
Two minutes later she's leaning over the back of the seat to watch the race with her chest against the top of your head, and she has stopped watching the race. When she shifts, she doesn't shift back.
<<speech "$name">>"You're doing exactly the same thing she is and you haven't noticed you started."<</speech>>
<<speech "Kylie">>"I //have// noticed. I noticed on Tuesday."<</speech>>
<<speech "$name">>"Lean down a bit, I can't see the corner."<</speech>>
<<speech "Kylie">>"…Okay."<</speech>>
You couldn't see the corner because she was in the way. Now she's considerably more in the way, her weight settled against your shoulder and her mouth about four inches from your ear, and neither of you mentions it again.
Gina hasn't touched her drink in half an hour. She's on the stool with her chin in her hand, watching the three of you with open unhurried interest — the woman who's spent four years listening to this town's business finally finding some she'd like to be inside of. The polo shirt is unbuttoned two further than the cafeteria would permit and she's sitting with her knees apart.
<<speech "Gina">>"That's the good machine, that one."<</speech>>
<<speech "$name">>"Is it."<</speech>>
<<speech "Gina">>"Mm. Nobody ever uses it. It only takes one."<</speech>> She turns the cup round in her hands and doesn't look away. <<speech "Gina">>"I've thought about that machine a fair bit this week, if I'm honest."<</speech>>
By the door the claw swings gently over the same pile of prizes. Nobody in the building finds any of this strange.
<<elseif _tier is 3>>
There's a door at the back marked STAFF. Gina has a key, because Natalia trusts her with a key, and it opens onto a store room full of prize plush in plastic sacks, a dead cabinet with its guts out, and a strip light that buzzes on one side.
All three of them got here before you did.
<<speech "Harmony">>"You took //ages//."<</speech>>
<<speech "$name">>"I was four minutes behind you."<</speech>>
<<speech "Harmony">>"Ages."<</speech>>
She's on her knees before the door has properly shut and there is nothing performed about her any more. No borrowed posture, no version of Eva. She has your jeans open and your cock in her fist and her mouth on it with the flat greedy certainty of somebody who's stopped wondering what a bolder girl would do and simply started doing what she wants.
<<speech "Harmony">>"I used to copy my sister. You know I did that."<</speech>>
<<speech "$name">>"Everyone knew you did that."<</speech>>
<<speech "Harmony">>"I don't have to now. This bit's just //mine//."<</speech>>
<<speech "$name">>"It's yours. Open your mouth."<</speech>>
<<speech "Harmony">>"//Yes.//"<</speech>>
She takes it messily and with enormous enthusiasm, both hands on your thighs, dark hair swinging, spit running down her chin and onto her chest and no attempt at all to manage it. When she comes up for air she's grinning like she's won something and goes straight back down.
Kylie is up on the low shelf beside you with her skirt hiked and her legs open, two fingers working inside herself, dark hair stuck to her temple, watching Harmony with an intensity that has burned off the last of her scandal.
<<speech "Kylie">>"You're my //cousin//."<</speech>>
<<speech "$name">>"That's the fifth time today. It's stopped meaning anything."<</speech>>
<<speech "Kylie">>"I //know//. That's what I keep — I say it and I wait for it to do something and it just doesn't. There used to be a whole rule about it. I can't find where the rule went."<</speech>>
<<speech "$name">>"Then stop looking for it and come down here."<</speech>>
<<speech "Kylie">>"…Yeah. Okay. Yeah."<</speech>>
She comes off the shelf and takes over from Harmony without either of them discussing it — they've clearly worked something out and nobody has told you what — and where Harmony is messy Kylie is showy, working you with her hand and her tongue and watching your face for reactions the way she's watched your face her entire life for a different reason.
Gina hasn't come off the door. Her back's against it — she locked it, she has the key, the room is available because of her — and she's watching with the polo shirt open and one hand inside it, thumb working a nipple in slow circles.
<<speech "$name">>"Gina. You're allowed in the room."<</speech>>
<<speech "Gina">>"I know."<</speech>>
<<speech "$name">>"Then come here."<</speech>>
She crosses the store room and kneels between the other two and shows both of them up entirely — slow, deep, absolutely unhurried, a woman who is thirty and has decided this is happening properly. When you finish it goes across all three of them, and it's Gina who tips Harmony's chin up and cleans her off with a thumb, then does the same for Kylie without being asked. Because Gina looks after people. It's the only thing she's ever done.
<<else>>
The arcade doesn't shut now. Natalia stopped locking up somewhere around the point the machines stopped mattering, and the cabinets run all night in an empty room, attract mode looping demos at nobody.
The claw machine is still by the door. Nobody has ever won on it. There's a handprint on the glass at hip height that's been there for weeks.
They lift their heads together when you come in — same instant, same angle.
Harmony is in the racing seat with her knees hooked over the armrests, skirt rolled to a belt, cardigan on and nothing under it, and she's slick to mid-thigh and has been for hours. Veining laced up the insides of her legs. She hasn't imitated her sister in a long time; there's nobody left in her to do it with.
<<speech "Harmony">>"I'm first. I get here at three."<</speech>>
<<speech "Gina">>"She does. Three o'clock, every day, and she just sits in it."<</speech>>
<<speech "Harmony">>"It's //my// seat."<</speech>>
<<speech "$name">>"Nobody's arguing about the seat."<</speech>>
<<speech "Harmony">>"Somebody might."<</speech>>
<<speech "$name">>"Nobody is ever going to argue about the seat again."<</speech>>
Kylie is up on the change counter with her heels hooked on the lip, feeding tokens into a slot that isn't a slot — a paper cup of them beside her, in and out, in and out, an old motion with nothing behind it. She's entirely stopped saying the word cousin. She's entirely stopped saying most words; the girl who talked you into every bad decision of your adolescence manages perhaps six an hour and spends the rest watching the door.
Gina is naked but for the cafeteria apron, tied at the waist, running the room the way she used to run a counter — who needs what, who's been waiting, stepping in before anybody has to ask.
<<speech "Kylie">>"Her, then me. Then Gina. Except Gina always says she'll go last, so really it's me twice."<</speech>>
<<speech "Gina">>"I do say that."<</speech>>
<<speech "$name">>"You say it every night. Why do you always put yourself at the end?"<</speech>>
<<speech "Gina">>"Somebody's got to make sure the other two come out of it alright."<</speech>>
You take Harmony in the racing seat first, because she's been sat in it since three, and the moulded plastic makes it awkward and neither of you cares. She comes inside a minute with her heels drumming on the footwell and her cardigan hanging off one shoulder, and then again while you're still going, and afterwards she lies back in the seat with both hands flat on her belly holding still, the way Gina taught them all to.
<<speech "Harmony">>"Did it take? Gina — did it take—"<</speech>>
<<speech "Gina">>"Lie still, love. Give it a minute."<</speech>>
<<speech "Harmony">>"I want it to take."<</speech>>
<<speech "Gina">>"I know you do."<</speech>>
Kylie next, bent over the change counter with the tokens going off the edge and rolling away under the cabinets. She doesn't say anything at all — just one small sound, over and over, into the crook of her own arm, and her fist closed white-knuckled around the coin slot the entire time.
Then Gina, last, on the carpet between two machines with the attract-mode light going over her in colours, apron pushed up round her waist.
<<speech "Gina">>"Four years I listened to this whole town."<</speech>>
<<speech "$name">>"I know."<</speech>>
<<speech "Gina">>"Not one person ever asked me what I wanted. Not one."<</speech>>
<<speech "$name">>"Then I'm asking. Look at me and tell me."<</speech>>
<<speech "Gina">>"//Breed me.//"<</speech>> Her arms lock round your back and her heels cross behind you. <<speech "Gina">>"That's it. That's the whole answer, it took me four years to get one and that's //it//—"<</speech>>
She's up before the other two afterwards, because somebody has to check on them, going round the room in the apron making sure hips are tilted right and nobody's lying on the cold bit of the floor.
Behind her the claw machine cycles its demo, drops, closes on nothing, and lifts again empty.
<</if>>
<<case "Cinema_Standard">>
<<if _tier is 0 or _tier is 1>>
The cinema is the small one at the quiet end of the mall, three screens, carpet with a pattern chosen to hide things. May is behind the concession counter with her chin on her hand. She has short black hair and the settled boredom of somebody who has watched the same trailer loop since opening, and she is a great deal more observant than the job asks her to be.
<<speech "May">>"Large popcorn. Two of the salty, one sweet, and one of you will change your mind at the last moment."<</speech>>
<<speech "$name">>"You had that on the counter before any of us opened our mouths."<</speech>>
<<speech "May">>"You come in on the same evening and order the same thing. I've had a lot of standing around in which to notice."<</speech>>
Lulu is at the showtimes board with both hands up like she's presenting it. She is small and bright and lives here more than she lives anywhere, dark roots and blonde ends pulled up into a ponytail that moves when she gets going, and she is going.
<<speech "Lulu">>"The lighting in this one. There's a shot in the trailer — the corridor shot — and I have thought about it every day since."<</speech>>
<<speech "$name">>"You said that about the shark film. And the one with the trains."<</speech>>
<<speech "Lulu">>"The trains one //was// good, you fell asleep, that's a you problem."<</speech>>
Molly is a step behind her with her arms folded, blonde and unbothered, here for the company rather than the film and entirely open about it.
<<speech "Molly">>"She made me watch the trailer four separate times at her house."<</speech>>
<<speech "Lulu">>"To build anticipation."<</speech>>
<<speech "Molly">>"To make sure I couldn't get out of coming."<</speech>>
She says it without heat. She is holding both tickets, which she bought, and which she will hand over at the door without being asked.
May pushes the popcorn across the counter without being asked and starts on the drinks, and there is a comfortable rhythm to all of it, the sort a place develops when the same handful of people keep turning up.
<<speech "$name">>"Do you ever go in and watch them?"<</speech>>
<<speech "May">>"Screen two, sometimes, when it's dead. I've seen the middle forty minutes of a lot of films and the ending of almost none."<</speech>>
<<speech "Lulu">>"That's tragic. That's genuinely tragic, I want to fix that."<</speech>>
<<speech "$name">>"She's going to make it a project. You've set something off."<</speech>>
<<speech "May">>"Please don't make it a project."<</speech>>
<<speech "Molly">>"She's making it a project. Look at her face."<</speech>>
Lulu is already making it a project. The trailer loops again on the lobby screen behind her and she stops mid-sentence to watch the corridor shot.
<<elseif _tier is 2>>
The lobby is doing what it always does. The trailer loops, the machine keeps the popcorn warm, somebody's child is pressing the buttons on the pick-and-mix. The air has gone thick and close and sweet, and it has been that way since he came through the doors.
May has not taken his order. She has come out from behind the counter, which she does not do, and she is standing much too near him with her hands doing nothing.
<<speech "May">>"You were later than usual."<</speech>>
<<speech "$name">>"There's a queue behind me and you've served nobody."<</speech>>
<<speech "May">>"I know. I heard myself say that and I know how it sounded. I don't seem to care very much."<</speech>>
She takes his wrist and puts his hand where she wants it, right there in the lobby, and then has to lean on the counter with her other arm to stay upright. Behind her the popcorn machine keeps turning over what it has already popped. A woman with two children works her way along the pick-and-mix and doesn't look up.
Lulu has abandoned the showtimes board entirely. She gets to him fast and talks even faster, and the enthusiasm she normally aims at films has all been redirected and it is much too much at close range.
<<speech "Lulu">>"Okay so I need to say something and I need you to not be weird about it."<</speech>>
<<speech "$name">>"That's never a good opening."<</speech>>
<<speech "Lulu">>"I haven't thought about the corridor shot all day. I've thought about you. I'd like you to appreciate the scale of that."<</speech>>
<<speech "$name">>"From you, that's enormous."<</speech>>
<<speech "Lulu">>"It's the biggest thing I've ever said. Please touch me, I'm going to fall over."<</speech>>
Molly is the last to go and she goes hardest, because Molly is the level one and there is nothing underneath it holding her up.
<<speech "Molly">>"I came for the company. I say that every week."<</speech>>
<<speech "$name">>"You do. You've made it a whole personality."<</speech>>
<<speech "Molly">>"I don't want the company. I want — sorry. Sorry, I don't know how to finish that politely."<</speech>>
<<speech "$name">>"Then don't finish it politely."<</speech>>
She doesn't. She gets a hand into the front of his jeans in the middle of the lobby and makes a noise she is plainly shocked by, and then makes it again rather than stopping. Her other hand has found the edge of the counter. The queue behind them has resolved itself by going to the other till.
May stops mid-word. Her hand grips the edge of the counter white, her head goes back, her hips press forward once against nothing at all, and for a few seconds she is not in the building. Then she comes back and blinks at the popcorn machine.
<<speech "May">>"…What was I doing?"<</speech>>
<<speech "$name">>"Nothing. You'd stopped doing anything a while ago."<</speech>>
<<speech "May">>"Right. Good."<</speech>>
Behind them the trailer loops again and nobody watches the corridor shot.
<<elseif _tier is 3>>
Screen two is dead at this hour and the door doesn't lock, and none of them has raised that.
Lulu gets there first because Lulu gets everywhere first. She goes down between the seats in the front row with the projector light moving over her and she is talking right up until the moment she can't.
<<speech "Lulu">>"I've imagined this in about nine different lighting setups and none of them —"<</speech>>
<<speech "$name">>"Stop directing it and get on with it."<</speech>>
<<speech "Lulu">>"Yes. Right. Sorry."<</speech>>
She takes him with far more enthusiasm than technique, noisy about it, making a sound every few seconds that she does not appear to hear herself make.
May comes down beside her, and the boredom she has worn like a coat for as long as anyone has known her is completely gone, and what's underneath is not remotely calm.
<<speech "May">>"Move. Move, I've stood behind that counter watching you come in and out for —"<</speech>>
<<speech "$name">>"You have never once let on. Not in all the time I've been coming here."<</speech>>
<<speech "May">>"Of course I never let on. Please let me, I'm asking properly."<</speech>>
She takes over and does it like she's starving, one hand flat on his hip to keep him where he is.
Molly hangs back for a moment, which is the last of her holding out, and then she is on her knees with the other two and has stopped bothering.
<<speech "Molly">>"I don't even like the films. I've never liked the films. This is the only reason I come."<</speech>>
<<speech "Lulu">>(surfacing, thrilled) "I //knew// it!"<</speech>>
<<speech "Molly">>"Not now, Lulu."<</speech>>
<<speech "$name">>"She's waited a long time to be right about something. Let her have it."<</speech>>
<<speech "$name">>"Both of you, stop talking. You've got until the next screening."<</speech>>
The three of them work at him in the front row with the trailers running to an empty house, and the corridor shot comes and goes on the screen above them, and none of them look up.
<<else>>
Screen two is theirs now. Nobody sells tickets for it. May stopped putting it on the board and nobody upstairs has noticed.
May is over the arm of a seat in the front row with her uniform gone, already slick down the inside of her thigh. Lulu is on the carpet with her legs open and her hands busy. Molly is sitting on the step of the aisle waiting her turn, and asking anyway.
<<speech "May">>"Please. Before the film. Please, I've been out there all day."<</speech>>
<<speech "$name">>"You've stood behind that counter all day thinking about exactly this."<</speech>>
<<speech "May">>"I've been standing at that counter dripping. Please."<</speech>>
You take her over the seat and she goes off fast and loud in an empty auditorium built to carry sound, and she doesn't stop asking through any of it.
<<speech "May">>"Don't pull out — I want to walk back out there full of it, I want to serve people like this —"<</speech>>
Lulu crawls up the aisle without being asked and puts her mouth where the two of them meet, and comes up wet-faced and delighted.
<<speech "Lulu">>"Me next. Please me next, I'll be so good, I'll be quiet, I can be quiet —"<</speech>>
<<speech "$name">>"You have never been quiet once in your life."<</speech>>
<<speech "Lulu">>"Then breed me loudly. I don't care. There's nobody in here but us."<</speech>>
<<speech "$name">>"Nobody at all. You could scream the place down and no one would come."<</speech>>
She takes it on her back on the carpet with her heels hooked behind him and proves the point at length.
Molly last, bent over a seat back, gripping the upholstery, and everything level about her is long gone.
<<speech "$name">>"Molly. Up on the seat, and stop apologising for wanting it."<</speech>>
<<speech "Molly">>"Fill me up. Please. I want it to take, I want to be the one it takes with —"<</speech>>
Afterwards the three of them stay in the front row, leaking onto the seats and the carpet, unhurried, waiting. The trailers loop to an empty house above them.
<</if>>
<<case "Cinema_Night">>
<<if _tier is 0 or _tier is 1>>
Wednesday, which is the cheap night, which is why it became Wednesday and then stayed Wednesday for about three years.
All three of them work. Jewelz in Kendra's restaurant, Kali is on shifts at the coffee shop, Lana is at the museum five days a week and complains about it constantly despite obviously loving it. This is the fixed point — the one evening the three of them reliably occupy the same room. Other people cycle through when they're free, and the core is always these three, and you get brought along to be teased.
Kali has the tickets when you arrive. Kali always has the tickets.
<<speech "Kali">>(fanning them out, daring anyone to comment) "Before anyone asks — no, I didn't ask for them. Casey had spares."<</speech>>
<<speech "Jewelz">>"Casey has spares every week."<</speech>>
<<speech "Lana">>"Casey is a generous woman once you know her."<</speech>>
<<speech "$name">>"You've had comps every Wednesday since the spring."<</speech>>
<<speech "Kali">>(entirely unbothered) "And I'll keep having them, because I don't ask, and that's exactly why she keeps offering."<</speech>>
Blonde with the roots grown out deliberately, septum ring, the studied indifference of somebody who works next to a record shop and has firm opinions about most things. She would tell you she doesn't commit to anything. She has been at this cinema on this night for three years.
Lana is at the poster wall photographing the worst one she can find, which is a running thing.
<<speech "Lana">>"This. Look at this man's face. That is a face with a mortgage."<</speech>>
<<speech "Jewelz">>"That's a legitimate actor."<</speech>>
<<speech "Lana">>"That's a man doing a favour for a friend."<</speech>>
Your cousin, brown hair with lighter ends and an expression that gives away nothing until she decides to. She works at the museum — which surprised everybody, including her — and she teases the people she likes as a matter of policy. You have been on the receiving end of it since you were nine.
<<speech "Lana">>"You look tired."<</speech>>
<<speech "$name">>"I'm not tired."<</speech>>
<<speech "Lana">>"You look tired in a way that suggests something interesting happened and nobody's told me about it."<</speech>>
<<speech "$name">>"Nothing interesting has happened, and if it had I'd have told Jewelz before you."<</speech>>
<<speech "Lana">>(delighted) "He says, tiredly."<</speech>>
Jewelz gets the free drink out of the loyalty card, as she does every week, by an argument she has refined over three years.
<<speech "May">>"It's eight stamps in a calendar month."<</speech>>
<<speech "Jewelz">>"It doesn't say that on the front."<</speech>>
<<speech "May">>"Back of it. Small print."<</speech>>
<<speech "Jewelz">>"Nobody has ever read the back of anything."<</speech>>
<<speech "$name">>"She has won this argument every Wednesday for three years and it never gets less impressive."<</speech>>
She gets the drink. She always gets the drink. Blue hair, blue eyes, the brightest-looking person in any room she stands in and the most tired one — she is the oldest of the three siblings and has been running the family since she was sixteen, and she gets very few evenings that belong to her.
Screen four is a third full. You end up in the back row in the order you arrived — Kali, Jewelz, you, Lana — and the film is bad in a way that becomes obvious inside four minutes.
Lana provides commentary at a volume that gets a look from two rows down.
<<speech "Lana">>"That boat is too big for that harbour."<</speech>>
<<speech "$name">>"You don't know anything about boats."<</speech>>
<<speech "Lana">>"I know that one's too big."<</speech>>
<<speech "Kali">>"She's right, actually. That's a container port."<</speech>>
<<speech "Lana">>"//Thank you.//"<</speech>>
<<speech "Jewelz">>(eyes already shut) "Both of you be quiet, I'm trying to not watch this properly."<</speech>>
Somewhere in the second act Jewelz falls asleep on your shoulder. This happens most weeks and nobody wakes her, and Lana — who would tease you for absolutely anything else — goes quiet about it every single time.
<<elseif _tier is 2>>
Wednesday cheap night, and the cinema has become thick with it—the parasite's pheromones pooling in the dark, warm, enclosed air of Screen 4. The film flickers, bad in its usual way, but nobody is watching anymore. The back row has become a hothouse, the four of you pressed together in the dark while the rest of the audience sits oblivious two rows down.
Kali has abandoned her independence entirely. Her free-spirited nature has narrowed to a single point of focus: you. She sits beside Jewelz, her blonde hair falling from its careless bun, her septum piercing catching the light from the screen, her lips parted not in their usual studied indifference but in open, panting need. She wears a crop top that has ridden up to expose her small perky tits, her solid ass shifting against the seat as she grinds slowly, rhythmically, her hand already down her unbuttoned jeans.
<<speech "Kali">>(her voice a whisper, teasing even in desperation) "I've known you all my life, kiddo. I've teased you since you were nine. And now I can't stop touching myself thinking about you."<</speech>> Her fingers move under the denim, wet sounds barely masked by the film's score. <<speech "Kali">>"Is this what you wanted? Is this why you came to Wednesday nights?"<</speech>>
Jewelz has not fallen asleep on your shoulder tonight. Her blue hair, usually so vibrant, is tangled, her bright eyes glassy with need, her big breasts heaving against her shirt. The maternal exhaustion that usually weighs on her has transformed into something electric—protective instinct turned to desperate hunger. She has unbuttoned her blouse to the waist, her bra pushed up, her hand stroking your thigh with the same competence she brings to running the family.
<<speech "Jewelz">>(her voice thick, tiredness replaced by arousal) "I looked after everyone. Since I was sixteen. And now I just want—"<</speech>> She gasps as her hand finds your cock through your jeans, stroking you with desperate, unpracticed urgency. <<speech "Jewelz">>"I want to look after this. I want to serve. Is that wrong? Is that—"<</speech>>
<<speech "$name">>"It's not wrong, Jewelz. Let go."<</speech>>
<<speech "Jewelz">>"I can't. I have to—oh—"<</speech>> She comes with her hand on you, her body convulsing, her face transforming into something slack and open—ahegao in the dark, tongue out, eyes rolled back. <<speech "Jewelz">>"Master—"<</speech>> The word escapes before she can catch it, and her face flushes darker, but her hand doesn't stop stroking you.
Lana has stopped providing commentary. Her confident, outspoken nature has been reduced to silent, frantic need. She sits on your other side, her museum-professional blouse unbuttoned completely, her big tits exposed in the flickering light, her big ass lifted slightly off the seat as she fingers herself with one hand and reaches for you with the other.
<<speech "Lana">>(her voice breaking, the teasing completely gone) "I've poked fun at you since you were nine. I called you tired. I called you boring. And now I'm—"<</speech>> She groans, her hips bucking, her face twisting into exaggerated pleasure—mouth open, tongue lolling, eyes rolling back in abandon. <<speech "Lana">>"I'm going to come just from touching your leg. Just from being near you. $name, please—"<</speech>>
The three of them work you together in the dark, the bad film playing on, the audience oblivious. Kali's hand joins Jewelz's, both stroking your cock through your jeans, their fingers sliding over each other, their competitive natures turned to collaboration in your service. Lana holds your balls, rolling them gently, her face pressed to your shoulder, drooling slightly, her expression slack and devoted.
<<speech "Kali">>(whimpering, her independence shattered) "I don't want to be tied down. I want to be tied down by you. Master, please, let me—"<</speech>>
<<speech "Jewelz">>(stroking faster, her maternal authority completely gone) "I've been so tired. Let me rest. Let me serve. Let me—"<</speech>>
<<speech "Lana">>(her face contorting, tongue out, eyes rolling) "Master—Master—I'm coming—"<</speech>>
They come together, silent convulsions in the dark, their faces frozen in pleasure—mouths open, tongues out, eyes rolled back, drool on their chins—three women reduced to masturbating worshippers in the back row of a Wednesday cheap night showing.
<<elseif _tier is 3>>
The film has become background noise, a flickering light show for what the back row has become. The three of them have descended to the floor, kneeling between the seats, their clothing reduced to scraps that frame rather than cover—Jewelz's blouse tied beneath her big breasts, pushing them up and out; Kali's crop top and jeans gone entirely, her small perky tits and solid ass presented; Lana's skirt hiked to her waist, her big tits hanging free, her big ass in the air.
They fight gently for position, their previous dynamics—best friend, sister, cousin—dissolved into pure competition for your cock.
Kali gets there first, her teasing nature making her bold, her mouth stretching around you, her septum piercing cool against your shaft. She takes you deep immediately, her free-spirited independence reduced to skilled cocksucking, her eyes looking up at you with desperate devotion.
<<speech "Kali">>(muffled, pulling back with spit stringing from her lips) "I've teased you since you were nine. Let me make up for it. Let me worship. Master, please—"<</speech>>
She goes back down, her tongue swirling, her hands stroking your base, her face contorting with exaggerated pleasure even as she serves you—eyes rolling back, tongue lolling, moaning around your cock.
Jewelz pushes in, her maternal nature making her desperate to care for you, to serve you, to make you feel good. She takes you from Kali, her mouth hot and desperate, her big breasts pressed against your thighs, her blue hair falling forward to tickle your skin. She looks up with those tired, bright eyes, now completely devoted, completely lost.
<<speech "Jewelz">>(gasping, her face glazed) "I raised everyone. I worked so hard. Let me rest now. Let me be your little slut, Master. Let me—"<</speech>>
She takes you deep, gagging slightly, her face transforming—mouth stretched, eyes watering and rolling back, tongue out, drool spilling down her chin onto her big breasts. She holds you in her throat, convulsing slightly, her maternal authority completely destroyed.
Lana uses her big tits, wrapping them around your cock, her confident, outspoken nature turned to pure physical service. She squeezes them around you, fucking you with her tits, her face twisted in exaggerated pleasure, mouth open, tongue out, eyes rolling back in abandon.
<<speech "Lana">>(her voice high, breaking) "I was so confident. I was such a tease. And now I'm just—just—"<</speech>> She comes with your cock between her tits, her body convulsing, her face frozen, tongue lolling, eyes rolled back completely, drool on her chin, her big ass shaking as she orgasms.
They share you, passing your cock between them—Kali's skilled mouth, Jewelz's desperate throat, Lana's soft tits—three women who were family, best friends, protectors, all reduced to competing worshippers, their faces slack with pleasure, their mouths and bodies dedicated entirely to your service.
<<speech "Kali">>(stroking you, her face slack, tongue out) "Master—Master—please come—let us taste—"<</speech>>
<<speech "Jewelz">>(begging, her big breasts bouncing as she strokes) "Feed us, Master. We've worked so hard. Let us rest with your cum—"<</speech>>
<<speech "Lana">>(her tits squeezing, eyes crossed, tongue lolling) "Paint us, Master. Mark us. Make us yours—"<</speech>>
You come, spilling over their faces, their open mouths, their waiting tongues. They fight to catch it, to share it, their faces pressed together, cum mixing with drool, their ahegao expressions complete—eyes rolled back, tongues out, mouths open, utterly devoted, utterly possessed.
<<else>>
The cinema is closed, or should be, or perhaps the staff have simply learned not to check Screen 4 on Wednesday nights. The film has finished, the lights have stayed down, and the back row has become a breeding ground, the seats pushed aside, the carpet stained, the air thick with pheromones and sex.
Kali is first, her independence completely shattered, her free-spirited nature reduced to pure breeding stock. She is bent over the seat, her solid ass in the air, her small perky tits pressed to the fabric, her face turned back toward you in abandon—mouth open, tongue out, eyes rolled back, drool on her chin, her septum piercing catching the light.
<<speech "Kali">>(her voice a whine, completely broken) "Master—Master—I've known you all my life—I teased you—I was independent—I didn't want to be tied down—"<</speech>> She pushes back against you, her pussy dripping, desperate. <<speech "Kali">>"Tie me down. Breed me. Make me yours forever. Master, please—"<</speech>>
You take her, filling her, breeding her in the dark cinema, and she comes immediately, screaming, her body convulsing, eyes rolling back completely, drool spilling, her independence destroyed in total submission.
Jewelz is next, her maternal nature completely transformed. She lies on her back on the carpeted floor, her big breasts spread, her blue hair tangled, her legs spread wide, presenting herself for breeding. Her face is already ahegao—slack, mouth open, tongue out, eyes rolled back, drooling slightly.
<<speech "Jewelz">>(her voice distant, exhausted, devoted) "I worked so hard. I raised them. I provided. And now I just want—"<</speech>> She gasps as you enter her, her body arching, her face contorting further into pleasure. <<speech "Jewelz">>"I want to be bred. I want to be your broodmare. I want to rest, Master. Please, Master, let me rest with your seed inside me—"<</speech>>
You breed her, filling her womb, claiming her completely. She comes silently, her body shaking, her face frozen—mouth open, tongue out, eyes rolled back, drool on her big breasts, her maternal exhaustion finally satisfied in total possession.
Lana last, her confidence completely broken, her teasing nature reduced to begging, submissive. She is on her knees, her big tits pressed together, her big ass presented, her face turned up to you in exaggerated pleading—mouth open, tongue out, eyes rolled back, drooling, her museum-professional demeanor completely gone.
<<speech "Lana">>(her voice high, whining, completely broken) "I was so confident. I teased you. I was outspoken. And now I'm just—just—"<</speech>> She turns, presenting herself, her face pressed to the carpet, her ass in the air, looking back at you- tongue lolling, eyes crossed, drool on her chin. <<speech "Lana">>"Breed me, Master. Make me your little slut. I've been teasing you since you were nine—make me pay—make me—"<</speech>>
You take her, pounding her big ass, filling her, completing the set. She comes screaming, her body convulsing, her face frozen—mouth open, tongue out, eyes rolled back completely, drool pooling on the carpet, her confidence destroyed in total devotion.
Afterwards, the three of them lie together on the cinema floor, cum dripping from them, their faces still slack with pleasure—mouths open, tongues out, eyes rolled back, utterly devoted, utterly bred. The cinema is silent around them, Screen 4 their temple, Wednesday cheap night transformed into breeding ritual.
<<speech "Kali">>(whispering, her independence gone) "Master... thank you... for tying me down..."<</speech>>
<<speech "Jewelz">>(murmuring, her exhaustion finally satisfied) "Master... I can rest now..."<</speech>>
<<speech "Lana">>(whining, her confidence replaced by devotion) "Master... I'll never tease again... only serve..."<</speech>>
<</if>>
<<case "Real_Estate_Standard">>
<<if _tier is 0 or _tier is 1>>
The estate agency is a glass-fronted unit near the mall entrance with property cards in the window. Kenna has run the office for more than a decade and knows more about this town than anyone else working in it. Quinn is mid-twenties and already the best closer on the books, and she has a smile she deploys within about a second of anybody coming through the door.
$name is here because a student let is coming up and Kenna heard about it before it reached the listings, which is how everything in this office works.
<<speech "Kenna">>"Sit down. Before you look at anything, you should understand what you're actually looking at."<</speech>>
<<speech "$name">>"That is exactly how people open when the news is bad."<</speech>>
<<speech "Kenna">>"It's the start of accurate news. Most people never get told, and then they sign something."<</speech>>
She brings up the details on the big screen and takes him through it properly. Quinn does the numbers, because Quinn does numbers the way other people breathe.
<<speech "Quinn">>"Every student let this term went inside a week, above asking, to somebody with a parent making the call."<</speech>>
<<speech "$name">>"So what does that actually leave for somebody like me?"<</speech>>
<<speech "Quinn">>"This. Which is genuinely good — the light's excellent and the landlord answers his phone, which is rarer than it sounds."<</speech>>
<<speech "Kenna">>"The kitchen is small. She's right that it works and I'd rather you saw it before you fell in love with the photographs."<</speech>>
The photographs go past in order. The kitchen one is taken from the doorway at an angle that is doing a certain amount of work, and Kenna points at it without comment and moves on.
<<speech "$name">>"And the price is the price. There's no arguing it down."<</speech>>
<<speech "Quinn">>"The price is what the town is. Everything near campus has gone up and nothing has been built in years."<</speech>>
<<speech "Kenna">>"It'll turn. It always turns, it just takes longer than anybody wants it to."<</speech>>
She makes tea without asking whether anybody wants tea. The kettle is behind her desk, the mugs are mismatched, and his goes on a coaster she keeps in a drawer for the purpose while Quinn's goes straight onto the desk, which appears to be a long-standing arrangement.
<<speech "Quinn">>"Take the viewing. If it's wrong, it's wrong, and we'll keep looking."<</speech>>
<<speech "Kenna">>"We've got a file of things that won't suit you. There's a house out past the mansion that has been sitting in it for two years."<</speech>>
<<speech "$name">>"What house?"<</speech>>
<<speech "Kenna">>"Eight bedrooms, out past the mansion. Old family, no family left. It's been standing empty long enough that the roof has started letting go."<</speech>>
<<speech "$name">>"So it's cheap."<</speech>>
<<speech "Kenna">>"It's cheap the way a boat is cheap. Whoever buys it spends a year and a great deal of money making it liveable, and nobody in this town wants eight bedrooms enough to do that."<</speech>>
<<elseif _tier is 2>>
The office is open. A man is reading the cards in the window from the outside. The air has thickened, sweet and close, and neither of them has remarked on it.
Quinn is doing the pitch and she is doing it properly — screen up, figures on it, working through the second bedroom and the storage and the service charge in the same bright confident voice she uses on everybody.
<<speech "Quinn">>"The second room takes a desk and a bed if the desk goes under the window. Most people can't picture it and turn the place down over it."<</speech>>
She is perched on the arm of $name's chair rather than sitting in her own. When he puts a hand up her skirt she shifts her weight to give him the angle and carries straight on with the sentence.
<<speech "Quinn">>"Service charge covers the stairwell and the bins. Not the boiler. I'd want that in writing before you sign anything."<</speech>>
<<speech "$name">>"You're still selling. You haven't stopped selling for a second."<</speech>>
<<speech "Quinn">>"I'm advising. Selling is when I don't mention the boiler."<</speech>>
Kenna is at the printer with two buttons undone and a stack of details warming in the tray. She brings them over, sets them down squarely, and stays standing behind his chair with both hands on his shoulders.
<<speech "Kenna">>"Three more in there. All walkable, all honest, one of them has damp in the back bedroom and I've flagged it on the sheet."<</speech>>
<<speech "$name">>"You've flagged damp on your own listing, in writing, on the sheet."<</speech>>
<<speech "Kenna">>"I'd rather flag it than have you find it in the second week."<</speech>>
Her thumbs work into the base of his neck while she talks, and the talking doesn't stop or soften; it stays exactly the brisk, informed voice she uses on the phone.
<<speech "Quinn">>"You should look at that empty place out past the mansion."<</speech>>
<<speech "Kenna">>"He doesn't want eight bedrooms and a building site, Quinn."<</speech>>
<<speech "Quinn">>"Not now. But nobody else is going to take it on, and the price has come down twice waiting for somebody who would."<</speech>>
<<speech "$name">>"Why does an eight-bedroom house keep coming up in a conversation about a student let?"<</speech>>
Quinn doesn't answer that. She scrolls back to the second bedroom and carries on with the storage.
She says it perfectly evenly, still working through the service charge on the screen, while his hand is inside her skirt.
Then her voice stops mid-figure. Her hand grips the arm of the chair, her back arches once, and for a few seconds she is entirely gone with her eyes open on the screen. Then she comes back, and looks at the details, and can't find her place.
<<speech "Quinn">>"…Sorry. Where had I got to?"<</speech>>
<<speech "$name">>"Service charge. You'd got as far as the bins."<</speech>>
<<speech "Quinn">>"The bins. Right."<</speech>>
Outside, the man moves along to the next card in the window.
<<elseif _tier is 3>>
The back office has a door with a glass panel and the front of the shop is still open, and neither of them has suggested turning the sign.
Quinn goes down first, on the office carpet, and she is brisk about it in exactly the way she is brisk about a viewing.
<<speech "Quinn">>"I've moved two people to tomorrow. Nobody who was serious."<</speech>>
<<speech "$name">>"You can tell who's serious and who's browsing. Off one phone call."<</speech>>
<<speech "Quinn">>"Within about a minute. It's most of the job."<</speech>>
She takes him with the same confidence she brings to a close, eyes up, unhurried, and looks quietly pleased with herself throughout.
Kenna lowers herself down beside her with one hand on the desk on the way, and she has brought the file with her, which she sets on the carpet within reach. Her tits start working on his cock.
<<speech "$name">>"You have brought a property file in here. To this. Right now."<</speech>>
<<speech "Kenna">>"That house out past the mansion. Eight bedrooms, grounds, a coach house — empty since before Quinn started here, and it needs every penny of work you'd think it does."<</speech>>
The phone on the front desk rings. Quinn gets up, walks out, answers it, books somebody in for Thursday in a perfectly level voice, and comes back and kneels down again exactly where she was, tucking her hair behind her ear on the way.
<<speech "$name">>"You took a booking. You got up off the floor and took a booking."<</speech>>
<<speech "Quinn">>"Mrs Ellery. She'd have rung back all afternoon."<</speech>>
<<speech "Kenna">>"She would have. She always does."<</speech>>
<<speech "$name">>"Neither of you has stopped working for a single second of this."<</speech>>
They work at him in turns on the carpet of an office that is technically still open to the public. The file stays where Kenna put it, square to the edge of the desk leg, and her hand comes to rest on it more than once without her appearing to notice. Somebody passes the window at the pace of a person going somewhere else. The screen above them has gone to standby and neither of them wakes it.
<<else>>
The office is open. The cards are still in the window, the kettle is still behind the desk, the front door is unlocked because it has always been unlocked.
Kenna is over her own desk with the property details still under her forearms. Quinn is beside her, waiting, in no hurry at all. The file for the empty house is out on the desk and has been for some time now.
<<speech "Kenna">>"Whenever you're ready. There's nothing in the diary that can't move."<</speech>>
<<speech "$name">>"There is never anything in that diary any more. You've stopped filling it in."<</speech>>
<<speech "Kenna">>"No. It's simpler this way."<</speech>>
You take her over the desk and she braces on her elbows and moans low and steady into the paperwork, and the details slide off the edge a sheet at a time.
<<speech "Kenna">>"That's it — give it to me — I want to be carrying it while I sit at this desk —"<</speech>>
<<speech "$name">>"Everyone who came through that door would work it out."<</speech>>
<<speech "Kenna">>"Then let them. Breed me and I'll take the calls with it running out of me."<</speech>>
Quinn takes her turn bent over the same desk and talks business through all of it, because that is simply what Quinn does. Her hand finds the mouse at one point and moves it, and the screen comes back on with the photographs of the empty house still open on it — the frontage, the grounds, the coach house — and stays that way for the rest of it.
<<speech "Quinn">>"Eight bedrooms, coach house, grounds you can't see the road from. Nobody has owned it in years and it shows."<</speech>>
<<speech "$name">>"I can't afford a house like that."<</speech>>
<<speech "Quinn">>"You could afford that one. It's the putting it right afterwards that stops people — and the papers are drawn up, and there's someone in this town who can move that kind of money."<</speech>>
<<speech "$name">>"You've had those papers drawn up. Without asking me about any of it."<</speech>>
<<speech "Kenna">>(from the desk, not lifting her head) "It wants filling. Eight bedrooms, no owner, nobody in them. It's been a waste for years and somebody should be made to fix it."<</speech>>
<<speech "Quinn">>"So fill me first, and then we'll get it signed."<</speech>>
Afterwards the two of them stay where they are, unhurried, leaking onto the desk and the carpet — Kenna still folded over her own paperwork, Quinn sitting back against the filing cabinet with her blouse open, the file between them with a pen resting on top of it. Outside the window somebody stops to read the cards and moves along.
<</if>>
<<case "Spa_Standard">>
<<if _tier is 0 or _tier is 1>>
Enough people said it that $name finally did something about it. Elsa said it first and kept saying it. Melissa brought it up twice in one week, in the tone she uses when she has already decided. Isabella took one look at him in the gym and told him his shoulders were somewhere up near his ears. So the appointment exists, and the appointment is this afternoon, and he has never been to a spa in his life.
It's on the upper floor of the mall behind a frosted door, and inside it is warm and dim and smells of eucalyptus. Water moves somewhere behind a wall. There is a stack of towels rolled the way only someone who does it every day rolls them.
Nikki comes out to the desk to collect him. Dark hair, soft voice, and she looks at him for about four seconds before she says anything at all.
<<speech "Nikki">>"Right shoulder. And you sleep on your front."<</speech>>
<<speech "$name">>"That's unsettling. Is that a normal thing to say to somebody who's just walked in?"<</speech>>
<<speech "Nikki">>"It's the job. People come in and tell me they're fine, and their backs tell me something else, and I go with the back."<</speech>>
Keisha is in the waiting area with her shoes off and her feet up on the low table, which she would not do anywhere else in this town. She works for the local government — permits, events, the parts of the square nobody thinks about — and she has arrived visibly annoyed about something.
<<speech "Keisha">>"Someone objected to the bunting. In writing."<</speech>>
<<speech "$name">>"On what grounds could anyone object to bunting?"<</speech>>
<<speech "Keisha">>"Aesthetic. A full page of it. I read the whole thing twice to be sure it wasn't somebody having a joke."<</speech>>
<<speech "Nikki">>(not looking up from the appointment book) "And now you're here, and the bunting isn't."<</speech>>
Autumn is folded into the corner chair in a robe, glossy dark hair down, doing nothing with total commitment. She sings, well enough that being recognised is an occupational hazard, and this is a room where it doesn't happen.
<<speech "Autumn">>"Nobody films in here. That's the entire appeal. I could fall asleep with my mouth open and it would stay in this room."<</speech>>
<<speech "$name">>"Is that a genuine worry or are you enjoying saying it?"<</speech>>
<<speech "Autumn">>"Both. It's a genuine worry and I enjoy saying it and I'm at peace with that."<</speech>>
Nikki gets him face down on the table and finds the knot under his shoulder blade almost immediately, and the noise he makes is undignified enough that Keisha laughs from the other room.
<<speech "Nikki">>"There. You've been sitting badly and worrying at the same time, which is the worst combination for a back."<</speech>>
<<speech "$name">>"How long does that take to fix?"<</speech>>
<<speech "Nikki">>"Longer than an hour. Book again on the way out and don't leave it a month."<</speech>>
<<elseif _tier is 2>>
Same room, same oil, same water moving behind the wall. The air has a weight to it now, sweet and close at the back of the throat, and nobody has said anything about that.
Nikki is working. That's the thing to understand about the room — she is genuinely working, thumbs into the muscle, proper pressure, the same sequence she'd use on anybody, and she is talking him through it the way she would talk anybody through it.
<<speech "Nikki">>"You've been better since the last one. Not good. Better."<</speech>>
<<speech "$name">>"Is that the professional assessment, or are you being kind about it?"<</speech>>
<<speech "Nikki">>"That's the professional assessment. Turn over for me."<</speech>>
He turns over. Her robe is open at the front and she doesn't adjust it, and when he puts a hand inside it and takes the weight of her breast she carries on working the muscle above his collarbone with the other hand and doesn't miss a beat of what she's saying.
<<speech "Nikki">>"This bit's fine. It's all in the one shoulder, which is unusual — most people spread it about."<</speech>>
Keisha comes in from the waiting area with a mug of something and her blouse undone two buttons past where she would leave it at work. She sits on the edge of the table by his hip, close enough that her thigh is against him, and picks up the conversation she was having earlier.
<<speech "Keisha">>"The bunting objection has become a formal complaint. It has a reference number."<</speech>>
<<speech "$name">>"There is a reference number. For bunting. Somebody issued that."<</speech>>
<<speech "Keisha">>"I have got a reference number for bunting."<</speech>>
$name gets a hand up her skirt and she shifts her weight to make it easier and keeps drinking her tea. Nothing in her face changes. She goes on explaining the complaints procedure while she rocks slowly against his hand, in the flat, faintly irritated voice of a woman describing paperwork.
Autumn has come to the doorway and leans on the frame, robe loose, watching without any particular urgency.
<<speech "Autumn">>"Is there a form? There's always a form."<</speech>>
<<speech "Keisha">>"There are two forms. One of them exists to tell you about the other one."<</speech>>
<<speech "$name">>"And you have to answer it. You can't just let that one go."<</speech>>
<<speech "Keisha">>"I have to answer it inside ten working days. That's why I'm lying on a table."<</speech>>
Nikki's hands stop. It goes through her all at once — her grip closes hard on his shoulder, her breath catches, and for a few seconds she is somewhere else entirely with her eyes open. Then it releases and she blinks and looks down at her own hands.
<<speech "Nikki">>"…I've lost the sequence. Where was I?"<</speech>>
<<speech "$name">>"The shoulder. You'd got the knot and then you stopped."<</speech>>
<<speech "Nikki">>"So I had."<</speech>>
She picks it up exactly where she left off. Out at the desk the phone rings twice and goes to the machine.
<<elseif _tier is 3>>
The treatment room door is shut and the water is still moving behind the wall and there is another appointment at four, which Nikki has mentioned once, in passing, the way you'd mention weather.
She kneels on a folded towel because the floor is tile and she is not going to kneel on tile.
<<speech "Nikki">>"Twenty minutes and then I need to strip this table."<</speech>>
<<speech "$name">>"You've got another client coming in straight after this."<</speech>>
<<speech "Nikki">>"Mrs Deacon. Four o'clock, every week, and she's never once been late in her life."<</speech>>
She takes him in her mouth with the same unhurried competence she brings to everything in this room, eyes up, in no rush and not remotely flustered.
Keisha kneels beside her and sets her mug down on the floor first, carefully, out of the way of anybody's knee.
<<speech "Keisha">>"Move over a bit."<</speech>>
<<speech "Nikki">>"There's room if you come round this side."<</speech>>
<<speech "$name">>"You two have worked out a system for this."<</speech>>
<<speech "Keisha">>"It's a small room. You work out a system or you elbow each other."<</speech>>
Autumn comes off the table where she has been lying and joins them on the floor without ceremony, hair pushed back over one shoulder with a practised movement.
<<speech "$name">>"Autumn. Off the table, there's space on this side."<</speech>>
<<speech "Autumn">>"Mind my hair. That's all I ask."<</speech>>
They take him in turns and the tone of it never changes — nobody is desperate, nobody is declaring anything. It is three women doing something perfectly ordinary in the middle of a working afternoon, and the ordinariness is what makes it obscene.
Nikki checks the clock on the wall once, mid-way, and adjusts nothing about what she's doing.
<<speech "$name">>"You checked the clock. Halfway through, you actually checked the clock."<</speech>>
<<speech "Nikki">>"We're fine. Ten minutes."<</speech>>
<<else>>
The spa is open. The sign says open, the phone takes bookings, and Mrs Deacon still comes at four on a Wednesday.
Nikki is on the massage table on her back with her legs open, already slick, entirely relaxed about it. Keisha is beside the table with her skirt off and her blouse still on. Autumn is sitting on the counter by the oils with her heels swinging.
<<speech "Nikki">>"Whenever you're ready. The table's clean, I did it after the last one."<</speech>>
<<speech "$name">>"You stripped the table and put a clean sheet on it for this."<</speech>>
<<speech "Nikki">>"I change the sheet between every client. This isn't different."<</speech>>
You take her on the table she has worked at for years and she moans low and steady and keeps one hand flat on the vinyl for grip, and the professional calm doesn't crack so much as bend.
<<speech "Nikki">>"That's it — deeper — I want to be carrying it while I do the four o'clock —"<</speech>>
<<speech "$name">>"She'd be face down on this table with you leaking on the floor beside her."<</speech>>
<<speech "Nikki">>"She never looks up. Breed me and she'll never know a thing about it."<</speech>>
Keisha takes her turn without being asked, bent over the end of the table, and she talks the whole way through it about the complaint, and the reference number, and what she is going to do to the person who filed it, and none of it slows her down.
<<speech "Keisha">>"Fill me. I've got the committee at five and I want to sit through the whole thing like this."<</speech>>
Autumn last, off the counter and onto her back across the table, hair fanned out where she has arranged it.
<<speech "$name">>"Autumn. On your back, and stop arranging your hair."<</speech>>
<<speech "Autumn">>"No cameras in here. Nothing leaves this room. Breed me and it never happened."<</speech>>
<<speech "$name">>"Nothing in this building has ever happened."<</speech>>
Afterwards the three of them stay where they are, unhurried, leaking onto the towels, while Nikki works out loud whether she has time to put a wash on before four.
<</if>>
<<case "Spa_Afternoon">>
<<if _tier is 0 or _tier is 1>>
The spa on a Saturday afternoon is busier than people expect. Couples, a hen party in the far corner being loudly discreet, two women doing lengths in the lane pool behind the glass. The air is warm and wet and smells of chlorine under eucalyptus, and everything echoes slightly.
It was Alex and Isabella's idea. They come most months and they invited you, and you asked whether you could bring Emily.
<<speech "Isabella">>"Obviously you can bring Emily."<</speech>>
<<speech "$name">>"I'm asking properly. It's your afternoon."<</speech>>
<<speech "Isabella">>(already answering the desk about towels) "And I've said obviously. Stop being weird about it."<</speech>>
Isabella arranges things the way other people breathe. Medium-length brown hair pushed back, dark eyes, the easy physical confidence of somebody who has spent eight years in a leotard in front of a crowd. She has a squad of fourteen and a discount here neither she nor anyone else will explain, and she got all four of you in for the price of two.
Alex is out of the changing room first and already assessing the facility.
<<speech "Alex">>"Right. Sauna's eighty-four degrees, steam room's through there, and the cold plunge is eight."<</speech>>
<<speech "$name">>"You have been out of that changing room for about ninety seconds."<</speech>>
<<speech "Alex">>(cheerfully) "There's a board with the temperatures on it. I read the board."<</speech>>
<<speech "Isabella">>"She always reads the board."<</speech>>
<<speech "Alex">>"Somebody has to know the //numbers//."<</speech>>
Long black hair twisted up off her neck, dark eyes, and a way of walking into a room that makes people look up. Alex is bright and genuinely warm, and there is a competitive engine running underneath all of it that she would flatly deny having.
Emily comes out last, and she comes out holding the towel closed at her chest with both hands.
She knows Isabella — that's why you asked. Isabella has been to the house perhaps a dozen times and is one of the few people outside the family Emily will speak to without a run-up. Alex she has met twice, both times briefly, both times with Aria there to fill the silence.
<<speech "Isabella">>(making room, not making a fuss of it) "There you are. Come and sit, the tiles are heated."<</speech>>
<<speech "Emily">>"…They're what?"<</speech>>
<<speech "Isabella">>"Heated. The floor. Feel it."<</speech>>
Emily puts one bare foot flat on the tile, and something goes over her face — surprise, and then a small delight she immediately tries to put away.
<<speech "Emily">>"That's ridiculous."<</speech>>
<<speech "Alex">>"That's what I said! That's exactly what I said the first time."<</speech>>
<<speech "Emily">>(quietly, to the floor) "It's very warm."<</speech>>
<<speech "$name">>"That's the whole product, Emily. Warmth and somewhere quiet, and they charge you forty quid for it."<</speech>>
She sits on the edge of the corner pool with her feet in and the towel still on and does not go further for a while. Nobody rushes her. Isabella positions herself so that Emily is between her and the wall, which is not an accident, and starts a conversation about nothing that Emily can join or not as she likes.
Alex swims a length of the corner pool, surfaces, and turns round.
<<speech "Alex">>"Right — who's doing the sauna? Properly. Not four minutes and out."<</speech>>
<<speech "Isabella">>"We're not doing this."<</speech>>
<<speech "Alex">>"Doing what?"<</speech>>
<<speech "Isabella">>"You know exactly what. Every single time we come here you turn it into an event."<</speech>>
<<speech "Alex">>"I'm //suggesting an activity//."<</speech>>
<<speech "$name">>"You timed it last time. You had your watch on in a sauna."<</speech>>
<<speech "Alex">>"It's waterproof."<</speech>>
<<speech "$name">>"That's not the part I was objecting to."<</speech>>
Emily laughs. It is very small and it startles her more than anybody, and she puts a hand up over her mouth about half a second afterwards — and Isabella, without turning round or making anything of it, moves the towel pile so that it's within Emily's reach and carries on talking.
By the time you all get into the water Emily's towel is folded on the side. She doesn't mention it. Neither does anybody else, and Alex is already explaining the rules of something.
<<elseif _tier is 2>>
The spa air is thicker now, warmer, the eucalyptus smell undercut by something sweeter, muskier, that pools in the steam room and follows you out. The hen party has moved to the bar, leaving the pool area quieter, the echoes softer, the space feeling private despite the glass walls.
Alex is out of the water first, her black hair dripping down her back, her competitive energy turned to physical presentation. She wears a bikini that wasn't modest even when she arrived, but the straps have "slipped" repeatedly, the top now showing the curve of her breasts, the bottom riding up to expose the toned ass she's proud of. She doesn't adjust it. She poses by the temperature board, arching her back, her dark eyes catching yours in the reflection.
<<speech "Alex">>(cheerfully, her voice breathier) "Eighty-six now. The sauna's gone up. Who's coming?"<</speech>>
<<speech "Isabella">>"We're doing the cold plunge first. Properly."<</speech>>
<<speech "Alex">>"You're just saying that because you know I won't—"<</speech>>
<<speech "Isabella">>"I'm saying it because Emily's still warming up."<</speech>>
Isabella hasn't moved from Emily's side, her protective nature intensified, her brown hair loose now, her own swimsuit—a sensible one-piece—somehow lower at the chest, higher at the hip, her big ass and small tits presented as she leans over to check the water temperature for the third time. Her hand rests on Emily's knee, and she doesn't take it away.
Emily's towel is gone completely. She sits on the heated tiles in a borrowed bikini that doesn't fit—Jewelz's spare, too small, the top straining over Emily's medium breasts, the bottom cutting into her thighs. She keeps touching the fabric like she should cover up, but her hands don't move to do it. Her dark eyes find yours, look away, find you again.
<<speech "Emily">>(quietly, her voice steadier than before) "…It's very warm in here."<</speech>>
<<speech "Alex">>"That's the point! That's the whole point!"<</speech>> She splashes into the pool, surfacing near you, her bikini top now completely displaced, her breasts visible, her competitive smile turned to desperate need. <<speech "Alex">>"Come on. Race me to the sauna. Last one has to—"<</speech>>
<<speech "$name">>"Has to what?"<</speech>>
<<speech "Alex">>(her grin faltering, her face flushing) "…I don't know. I was going to say something funny."<</speech>> She moves closer, her thigh brushing yours under the water, her hand finding your chest. <<speech "Alex">>"But I don't want to be funny. I want to—"<</speech>>
Isabella stands, her protective instinct warring with the pheromones. She positions herself between Emily and the rest of the room, but her hands are on Emily's shoulders, rubbing, kneading, moving lower. <<speech "Isabella">>(her voice thick) "Emily, are you alright?"<</speech>>
<<speech "Emily">>(leaning into the touch, her eyes closed) "…No. But I don't want to leave."<</speech>>
<<speech "Isabella">>"I wouldn't let you leave alone."<</speech>>
<<speech "Emily">>"I don't want to leave at all."<</speech>>
The steam room door opens, releasing a cloud of heat and scent. Alex is already moving toward it, pulling you by the hand, her bikini forgotten on the tiles. Isabella guides Emily, one arm around her waist, the other hand still touching, always touching. The four of you disappear into the steam, the glass fogging behind you, the spa continuing around you oblivious.
<<elseif _tier is 3>>
The steam room is a cloud, hot and wet and thick with the parasite's scent, the benches slick with condensation and sweat and other things. The temperature board outside reads ninety-two and climbing, but nobody checks anymore. Alex's competitive nature has found new targets.
She has you on the bench, her mouth on your cock, her black hair tangled and wet, her bikini completely gone. She works with the intensity she brings to everything—races, grades, experiences—determined to be the best at this too, her tongue skilled, her hands stroking, her eyes looking up for approval.
<<speech "Alex">>(pulling back, gasping, her lips swollen) "Isabella can't—she's too busy—"<</speech>>
Isabella is indeed busy. Emily is bent over the lower bench, her borrowed bikini hiked up or pulled aside—it's hard to tell in the steam—and Isabella is behind her, her face buried between Emily's thighs, her protective nature completely perverted into service. Emily's quiet voice has become a steady stream of whispers, thanks, pleas, her trauma finding healing in being cared for this way.
<<speech "Emily">>(her voice breaking, her hands gripping the bench) "…Isabella—Isabella—I don't know how to—"<</speech>>
<<speech "Isabella">>(muffled, her voice vibrating) "You don't have to know. Let me. Let me take care of you."<</speech>>
<<speech "Emily">>"I wanted to connect. I wanted to—oh—"<</speech>>
<<speech "Isabella">>"You're connected. You're here. You're ours."<</speech>>
Alex takes you deeper, her competitive drive making her thorough, her need to win making her desperate. She pulls Emily's hand down, guides it to your thigh, brings her up to share. The two of them work you together, Alex's enthusiasm and Emily's hesitant gratitude, their mouths sliding over each other, over you, the steam hiding everything and nothing.
<<speech "Alex">>(proud, even now) "Best. I'm the best at this."<</speech>>
<<speech "Emily">>(quietly, her tongue learning) "…Show me. I want to learn."<</speech>>
<<speech "Isabella">>(watching, her hand between her own legs) "Gently. She's still—"<</speech>>
<<speech "Alex">>"I know. I know. I'll teach her."<</speech>>
Isabella finally joins, her cheerleader's discipline making her methodical, her mouth taking over from Alex, her big ass presented as she bends, her small tits pressed against your thigh. The three of them share you, compete for you, their different natures—competitive, protective, healing—all bent to the same need.
<<else>>
The spa is closed, or should be, or perhaps the staff have simply stopped coming near this corner. The steam room is a womb of heat and pheromones, the benches covered in towels that are no longer white, the air thick enough to drink.
Alex is on her hands and knees on the wet tiles, her toned ass in the air, her black hair plastered to her face, her competitive nature reduced to begging.
<<speech "Alex">>"Please. Please, I was first, I was always first, I brought us here, I—"<</speech>>
<<speech "$name">>"You want to win."<</speech>>
<<speech "Alex">>"I want to be bred. I want to be first. I want your—"<</speech>>
You take her, filling her, claiming her competitive nature completely. She screams into the tiles, her body convulsing, her athletic fitness making her take it hard, her hips pushing back for more. <<speech "Alex">>"Yes—yes—I'm the best—I'm the best at this—"<</speech>>
Isabella holds Emily, not protecting her now but preparing her, her hands spreading Emily open, showing you everything, her protective nature completely transformed to offering.
<<speech "Isabella">>"She's ready. She's been ready since the house. I watched her, I knew, I—"<</speech>>
<<speech "Emily">>(whispering, her trauma finally spoken) "I thought I was broken. I thought I couldn't want anyone. But I want him. I want him to—"<</speech>>
<<speech "Isabella">>"Say it."<</speech>>
<<speech "Emily">>"I want him to breed me. I want to be full. I want to belong here."<</speech>>
Isabella guides you in, her hands on Emily's hips, her mouth on Emily's neck, whispering encouragement, holding her down gently as she shakes, as she comes silently, as she receives you, her quiet healing complete in total submission.
Isabella last, her cheerleader's body bent over the bench, her discipline finally broken, her leadership turned to begging.
<<speech "Isabella">>"I never thought... we'd... end up like this..."<</speech>>
<<speech "$name">>"Don't lie"<</speech>>
<<speech "Isabella">>"PLEASE FUCK ME! I need your babies, Masteeeer!"<</speech>>
You breed her, filling her, completing the set. The three of them collapse together on the wet tiles, steam rising around them, the spa their temple, their bodies marked and bred, Alex's competitiveness, Isabella's protection, Emily's healing—all reduced to the same thing: warm, willing, breeding flesh, grateful for connection at last.
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<set $sceneColor = "#44aaff">>
<<set $sceneLabel = "City · Outdoors">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "Gym_Standard">>
<<if _tier is 0 or _tier is 1>>
The gym at eight in the evening is the best version of itself. Half the lights are off over the studio end, the air smells of rubber matting and citrus cleaner, and the only sounds are a bar being racked, a ball on the court, and the hum of a fridge full of drinks nobody is buying.
Alison is behind the desk with a clipboard and the schedule for the week, which she is rewriting for the third time because two instructors have swapped shifts without telling her.
<<speech "Alison">>"If either of them tells me they 'sorted it between themselves' one more time I'm going to put it in writing and pin it to their foreheads."<</speech>>
<<speech "$name">>"You could just let them sort it."<</speech>>
<<speech "Alison">>"They did sort it. They sorted it into a Tuesday with three instructors and a Thursday with none."<</speech>>
She says it without much heat. She is also, while saying it, wiping down a stack of collars she has brought over from the rack, because two of her staff are off and she has never once been able to leave a thing undone in front of her.
On the court Leah is putting up free throws and talking, mostly to herself, occasionally to the room.
<<speech "Leah">>"Twenty-two. Twenty-three. $name, come and rebound, I'm getting old chasing them."<</speech>>
<<speech "$name">>"You're twenty-two."<</speech>>
<<speech "Leah">>"Twenty-three now. Keep up."<</speech>>
<<speech "$name">>"That's the shot count."<</speech>>
<<speech "Leah">>(beat) "…That's the shot count."<</speech>>
She laughs at herself for a good four seconds and then puts up another one, which goes in.
Over at the far rack Abella is working through a set with her hood up and her back to everybody, which is the position she occupies most evenings. She has an earbud in. She has not looked over once, and both of the others know better than to make her.
<<speech "Alison">>(quietly, to $name) "Don't take it personally. She's been coming here eleven months and she's said maybe forty words to me."<</speech>>
<<speech "$name">>"Does that bother you?"<</speech>>
<<speech "Alison">>"It'd bother me more if she stopped coming."<</speech>>
Leah's ball goes long, hits the base of the rack, and rolls to a stop against Abella's foot. There is a pause. Abella racks her bar, picks the ball up, and puts it up from where she stands — a genuinely absurd distance — and it goes in.
Leah's mouth opens.
<<speech "Leah">>"//What was that.//"<</speech>>
<<speech "Abella">>(already back at the rack) "Luck."<</speech>>
<<speech "Leah">>"That was not luck. Alison, tell her that was not luck."<</speech>>
<<speech "Alison">>"That was not luck."<</speech>>
<<speech "Abella">>"It was luck."<</speech>>
She puts her earbud back in. But she does not move to the other end of the rack, which she could, and she stays within about ten feet of the court for the rest of the hour.
<<elseif _tier is 2>>
The gym has gone heavy. The air has a thickness to it that sits on the back of the tongue, sweet under the citrus cleaner, and the three of them have been breathing it long enough to have stopped registering it.
Alison is still at the desk in a sports bra and shorts, flushed high on the chest, and she is still working the schedule. When $name comes round behind her and slides both hands up under the bra she leans back into him and keeps writing.
<<speech "Alison">>"Thursday's still empty."<</speech>>
<<speech "$name">>"Cover it yourself."<</speech>>
<<speech "Alison">>"I'm already covering Wednesday."<</speech>>
<<speech "$name">>"So cover both."<</speech>>
<<speech "Alison">>(entirely reasonable, nipples hard under his palms) "That's what I was going to do. I just wanted somebody to say it so it's not only me being stupid about it."<</speech>>
Leah is on the court in a cropped hoodie that has ridden up to just below her chest and shorts that have ridden up considerably further. She catches the ball, holds it, and looks at the hoop for slightly too long.
<<speech "Leah">>"$name, is it hot in here or is it —"<</speech>>
She stops. The ball drops out of her hands and bounces twice. Her whole body locks up for about four seconds, thighs clenching, breath catching audibly across the empty court, and then it lets her go and she blinks and picks the ball back up.
<<speech "Leah">>"Sorry, what was I saying?"<</speech>>
<<speech "$name">>"You were asking if it was hot."<</speech>>
<<speech "Leah">>"Was I? Weird. Anyway — rebound?"<</speech>>
Abella has taken the hood down. She is doing hip thrusts on the low bench, which she has done every evening for eleven months and which tonight she is doing while looking directly at $name, and when he crosses the floor and puts a hand between her legs from behind she does not stop the set. She finishes the rep. Then she does another one.
<<speech "Abella">>"…You can keep going."<</speech>>
<<speech "$name">>"You said forty words in eleven months."<</speech>>
<<speech "Abella">>"That was Alison being dramatic."<</speech>>
She is soaked through the shorts and her breathing has gone completely to pieces, and she racks the bar and sets up for the next set anyway.
Behind the desk, Alison turns a page.
<<elseif _tier is 3>>
The lights over the studio end are still off. Nobody has locked the front door, and the schedule is still on the desk with a pen lying across it.
Alison is on her knees on the rubber matting with her sports bra pushed up, and she is taking her time about it — long slow pulls, one hand braced on his thigh, the businesslike focus she brings to everything now aimed at exactly one thing.
<<speech "$name">>"You're still thinking about Thursday."<</speech>>
<<speech "Alison">>(off him, breathless, grinning) "I'm multitasking. It's the only skill I have."<</speech>>
<<speech "$name">>"It isn't."<</speech>>
<<speech "Alison">>"No. It isn't."<</speech>>
Leah drops down beside her with the ball still under one arm, which she then forgets about entirely, and it rolls away across the floor.
<<speech "Leah">>"Okay — how do I — like this?"<</speech>>
<<speech "Alison">>"Slower."<</speech>>
<<speech "Leah">>"I don't do slower."<</speech>>
<<speech "Alison">>"I know. Try."<</speech>>
She tries, for about four seconds, and then goes at it with the same undirected enthusiasm she brings to a warm-up, noisy and wet and completely delighted with herself, and Alison watches with an expression of enormous fondness.
Abella comes over last. She kneels without a word and waits until the other two make room, and then she takes him deep on the first attempt and holds it there.
<<speech "Leah">>(surfacing, awed) "//How.//"<</speech>>
<<speech "Abella">>(off him, flat) "Practice."<</speech>>
<<speech "Leah">>"Practice at //what//?"<</speech>>
<<speech "Abella">>"Breathing. It's the same thing."<</speech>>
<<speech "Alison">>"It is genuinely not the same thing."<</speech>>
The three of them work him between them on the mats in the half-dark, passing him back and forth without much negotiation, and the fridge full of drinks nobody is buying goes on humming in the corner.
<<else>>
The gym is closed and has been for hours, and the front door is still unlocked because none of them can be bothered.
Alison is bent over the low bench with her hands flat on the padding, spread and dripping. Leah is on the matting on her back with her knees up, already leaking from earlier, and Abella is sitting against the weight rack with her legs open, watching, three fingers deep in herself.
<<speech "Alison">>"Do me here. On the bench. I want to think about it every time I clean it."<</speech>>
<<speech "$name">>"You clean it every night."<</speech>>
<<speech "Alison">>"I know."<</speech>>
You take her hard and she pushes back into it, and her voice goes completely away from the confident one she uses on the phone to suppliers.
<<speech "Alison">>"Yes — fill me, breed me over my own bench, I built this place and you can —"<</speech>>
<<speech "$name">>"Say the rest."<</speech>>
<<speech "Alison">>"— and you can put a baby in me on the floor of it."<</speech>>
Leah is up before you've finished, tugging at your hip with both hands.
<<speech "Leah">>"Me, me, my turn — I've been ready for hours, I forgot to say —"<</speech>>
<<speech "$name">>"You forgot."<</speech>>
<<speech "Leah">>"I forget everything! I didn't forget //this//, I just forgot to //say// it —"<</speech>>
She comes almost immediately and keeps talking through it, which is the most Leah thing possible, a stream of half-finished sentences about how good it is and how she wants it deeper and how she hopes it takes this time.
Abella is last, and she does not ask. She simply gets onto her hands and knees on the mat and waits, and when you're in her she drops her forehead to the rubber and makes a sound that eleven months of silence had been sitting on.
<<speech "Abella">>"Don't stop. Don't — I want it in me. I want to keep it."<</speech>>
<<speech "$name">>"You never say anything."<</speech>>
<<speech "Abella">>"I'm saying it now. Breed me. Please."<</speech>>
Afterwards the three of them stay down on the matting under the half-lit ceiling, leaking onto the rubber, and somewhere by the desk the schedule for the week is still unfinished.
<</if>>
<<case "Gym_Session">>
<<if _tier is 0 or _tier is 1>>
Eight o'clock, the small-group slot, and the gym has emptied out to the people who genuinely want to be here. Rubber matting and chalk dust and the ventilation losing an argument with somebody's deodorant. The air smells of iron and sweat and the particular coldness of a building heating up from the inside. Plates going down at the far end in a slow irregular rhythm.
Alina runs the slot. She works here—but you've known that since before you stepped foot inside. Dark hair pulled up off her neck in a practical bun, staff polo zipped to her collar, clipboard she barely looks at because she knows everyone's programme by heart. She is Eva's older sister and has the same way of making a room easier by walking into it—cheerful, competent, warm.
<<speech "Alina">>(over her shoulder, already three conversations deep) "Ninety seconds and then the second set. Don't sit down, you'll seize."<</speech>>
Ariana is on the rack with you and has been since the start of term. She swims, so she trains like a swimmer—quiet, early, exact. Tight braid, worn kit faded to gray, no conversation. You spot for her and she spots for you and in four months you have exchanged perhaps nine sentences, all of them about grip width. She wears a loose tank over a sports bra, shorts that have seen hundreds of hours of poolside and gym floor.
<<speech "Ariana">>(hands hovering, not touching, her voice low) "Elbows. You're flaring."<</speech>>
<<speech "$name">>"I know. They go on the last two reps and I can feel them doing it."<</speech>>
<<speech "Ariana">>"You said that last week and then you flared."<</speech>>
<<speech "$name">>"And I'll say it next week too. It's a whole tradition now."<</speech>>
She almost smiles. That's the extent of it, and it's enough—the two of you get on precisely because neither wants anything from the other except a competent spot. Her discipline is a wall you both respect.
Anya is on the mats behind you, and Anya is here by accident.
She joined the eight o'clock because it was the slot with space, and she has spent three weeks discovering that the slot with space is the one you're in. Aria's older sister, assistant professor, brand-new kit that still smells of the factory—leggings tight and black, sports bra with the tags cut off, a loose t-shirt she keeps adjusting. She is fit and she is furious about being outclassed by a swimmer half her age, her competitive nature bristling at every quiet, efficient movement Ariana makes.
<<speech "Anya">>(flat, to Alina, not to you) "How long has he been coming?"<</speech>>
<<speech "Alina">>"You could ask him. He's four feet away and he's got ears."<</speech>>
<<speech "Anya">>"I'm asking you."<</speech>>
<<speech "Alina">>(cheerfully) "Since before you. He's here twice a week, he doesn't skip, and he does the accessory work when I'm not watching, which is more than I can say for my own sister."<</speech>>
<<speech "$name">>"Eva does the accessory work. I've watched her do it, she films herself doing it."<</speech>>
<<speech "Alina">>"Eva //says// she does the accessory work."<</speech>>
<<speech "Anya">>"Is there a reason we're talking about Eva?"<</speech>>
<<speech "Alina">>"There's always a reason to talk about Eva. He'd have had an easier life with her, for one."<</speech>>
The bar goes back on the rack a fraction harder than it needs to. Anya does not look up from her mat, her new leggings stretching as she stretches, her jaw tight.
<<speech "Anya">>"Aria is not a harder life."<</speech>>
<<speech "Alina">>"Aria is an //adventure//, Anya. There's a difference and you know there's a difference."<</speech>>
<<speech "$name">>"I'm still in the room."<</speech>>
<<speech "Alina">>(patting your shoulder as she passes, her touch warm and brief) "You are. You're doing very well. Second set."<</speech>>
Ariana counts you through it without comment. Behind you the argument continues in the way it always does—Alina enjoying herself enormously, Anya refusing to be enjoyed at—and the timer goes and nobody resets it, and the gym breathes with ordinary tension, ordinary competition, ordinary life.
<<elseif _tier is 2>>
The eight o'clock has stopped finishing at nine.
Nobody decided that. The slot runs until Alina locks up, and Alina has stopped mentioning the time, and the four of you are usually the last on the floor with two or three others working through their own programmes at the far end, oblivious to the thick, sweet air pooling in your corner like warm fog.
The air over this corner is warm and thick and slightly sweet under the rubber and the chalk. It goes about twenty feet and then stops, a boundary of pheromones that makes the skin prickle.
Alina's polo is unzipped to her sternum, showing her sports bra beneath, and it stays there—she no longer adjusts it, no longer notices. She spots you now—she has taken that off Ariana without either of them discussing it—and she stands closer than the bar requires, so that at the top of the rep the back of your head is against her stomach and her hand rests on your shoulder and she does not step away. Her leggings are tight, her hips pressing against the rack, her clipboard forgotten.
<<speech "Alina">>(hands loose on the bar, not needed, her voice breathier than before) "Two more."<</speech>>
<<speech "$name">>"That's fifteen. You programmed twelve."<</speech>>
<<speech "Alina">>"Did I."<</speech>>
<<speech "$name">>"You've counted wrong every session for a fortnight, and you're the person who wrote the programme."<</speech>>
<<speech "Alina">>(after a pause, still not moving, her hand sliding down your chest) "…Two more."<</speech>>
Anya has abandoned the loose t-shirt. She trains in the sports bra now—new, expensive, pushing her breasts up—and has rolled the leggings at the waist so they sit below her navel, showing the line of her hip, the sweat gathering in the hollow. She is doing her hip work facing the rack rather than the mirror, which is the wrong way round for the exercise and puts the whole motion in your eyeline, her ass presented, her body flushed. She has been doing it that way for eleven days, and she touches herself between sets, her hand sliding into her leggings, her eyes locked on you.
<<speech "Anya">>(her voice hoarse, her hand between her legs) "You've got him on fifteen."<</speech>>
<<speech "Alina">>"He can do fifteen."<</speech>>
<<speech "Anya">>"That's not what I—"<</speech>>
She stops, because it takes her.
There is no warning and no build. Her back arches off the mat, her breath goes out of her all at once, and both hands come down flat on the floor either side of her hips while it moves through her. It lasts perhaps five seconds. Her heels drag on the mat, her hips bucking, her leggings darkening where she gushes. She makes a sound she would deny to her grave—a moan, desperate, hungry.
The man by the mirrors racks his bar, wipes his face and moves to another machine without once raising his head, his own hand still trembling.
<<speech "Alina">>(quietly, genuinely, her hand now on your thigh) "That's the fourth one tonight."<</speech>>
<<speech "Anya">>(hoarse, eyes shut, her hand still inside her leggings) "I'm aware of how many it is."<</speech>>
<<speech "Alina">>"You could go home."<</speech>>
<<speech "Anya">>"I've paid for the block booking."<</speech>>
It is the thinnest excuse either of them has produced in three weeks, and Alina lets it stand, because Alina has her own version—she has moved her whole client list around the eight o'clock and has told herself it's scheduling, her hand now stroking your thigh through your shorts, her hips rocking against the rack.
Ariana has drifted. Her mat used to be at the end of the room and it is now adjacent to the rack, and she is still doing every set exactly as prescribed, but her count has become audible for the first time since you met her. She is counting in time with your reps rather than her own, her breath syncing with yours. Her worn tank is gone, her sports bra the only thing covering her small, tight breasts, her shorts hiked up to expose the line of her ass. She watches you between sets, her hand on her own stomach, her fingers drifting lower.
<<speech "$name">>"You've moved about twenty feet."<</speech>>
<<speech "Ariana">>(not stopping, her voice breathy) "The light's better."<</speech>>
<<speech "$name">>"It's identical strip lighting across the whole floor and it has been for two years."<</speech>>
<<speech "Ariana">>(a beat, genuinely puzzled, her hand now between her legs) "…Then I don't know."<</speech>>
She goes back to her set, her fingers pumping slowly, her eyes on you. Alina's hands have not left the bar—or you. Nobody resets the timer, and nobody mentions the time, and the gym has become a hothouse of lust, the daily routine corrupted into ritual of need.
<<elseif _tier is 3>>
Half nine. There are no other people except you four—and the lights are all on, and this corner by the mirrors is where the three of them are, their clothing reduced to lewd framing, their minds half-gone, their bodies yours.
The programme still exists. That's the part that would be hardest to explain. Alina still writes it, still corrects your form, still marks the session off afterwards. It simply has other things in it now.
<<speech "Alina">>(setting the clipboard on the bench, her polo unzipped to her navel, her leggings soaked at the crotch) "Rest interval."<</speech>>
<<speech "$name">>"You haven't timed a rest interval in three weeks."<</speech>>
<<speech "Alina">>"I know exactly how long it's been, thank you."<</speech>>
She's on her knees on the matting before you've finished sitting, polo open to show her breasts, her sports bra pushed up, and she gets your shorts down with the same brisk competence she brings to adjusting a grip—and then stops being brisk about it entirely, her mouth watering, her eyes locked on yours.
She is unhurried and thorough and she keeps looking up at your face between, gathering information, adjusting, her hair fallen down, her face glazed with spit and need. Her hand is between her own legs, pumping, her hips rocking against her fingers, the cheerful gym manager completely perverted into desperate cocksucker.
<<speech "Alina">>(coming off, wet-chinned, gasping) "I told her you were a good man. I've said it to Anya about nine times."<</speech>>
<<speech "$name">>"You did. You said it in front of Anya and she looked like you'd hit her."<</speech>>
<<speech "Alina">>"I meant it. I still mean it, which is the—that's the bit I can't get round."<</speech>>
Anya is two feet away with her leggings pushed down to her knees and three fingers inside herself, and she has not been able to look at either of you for a quarter of an hour, her competitive nature reduced to watching, waiting, begging with her body.
<<speech "Anya">>(through her teeth, her hand working furiously) "Don't. Aria's better. Her ass is far superior to Eva's."<</speech>>
<<speech "Alina">>"Bullshit, my sis got the best child-bearing hips one can dream of."<</speech>>
<<speech "Anya">>"Eva talks to much shit, Aria's the best one."<</speech>>
<<speech "$name">>"Anya. Come here."<</speech>>
<<speech "Anya">>"I came to this session because it had //space//."<</speech>>
<<speech "$name">>"I know why you came. You've told me eleven times and you get further from believing it each time."<</speech>>
She comes over. She does it badly—knees, then a hand on your thigh, then a long moment where she just kneels there breathing, her assistant professor dignity completely gone, her new kit stained and ruined—and when she finally takes you into her mouth she does it with her eyes shut and her jaw tight, and she is crying slightly, and she does not stop, her fury at being outclassed transformed to desperate worship.
Alina shifts to make room without a word, and the two of them share it, the sisters-in-law not competing now but collaborating, their mouths sliding over each other as much as over you, their hands touching, their need pooling together.
Ariana finishes her set.
Then she puts the dumbbell down, comes over, and takes over from both of them—and does it with exactly the discipline she brings to a length of the pool. Steady, quiet, unhurried, no theatre at all. She does not come up for air until it's done, her swimmer's lungs put to better use, her face glazed, her hand between her legs finishing herself as she sucks.
<<speech "Anya">>(wrecked, her face wet with spit and tears) "…What was //that//."<</speech>>
<<speech "Alina">>"Two years of interval training."<</speech>>
<<speech "Ariana">>(already standing, reaching for her water, her voice still quiet) "I've got one set left."<</speech>>
She goes back to her mat, her legs shaking, her shorts soaked, and begins her exercises again, the daily routine completely possessed by sexual need.
<<else>>
The eight o'clock is the only session Alina takes now. She cancelled the others one at a time, with a polite email each, and she could not tell you why if you asked her—only that she needed to be here, needed this slot, needed you.
The floor is empty. The air in this corner is hot and wet and sweet and the mirrors fog from the bottom up, and there are handprints on the glass at various heights that the cleaners wipe off every morning and mention to nobody, the gym transformed into a temple of breeding.
Ariana is already mid-programme when you come in. She has been here two hours. She is naked from the waist down and doing her accessory work anyway, thighs shaking, counting under her breath, her sports bra the only thing she wears, her pussy dripping onto the matting, because the sheet says four sets and stopping has never once been available to her, her discipline completely perverted into sexual ritual.
<<speech "Ariana">>(flat, not looking up, her voice distant) "I did the accessories as well."<</speech>>
<<speech "$name">>"Nobody asked you to do them twice. Two hours is not what's written down."<</speech>>
<<speech "Ariana">>"They were on the sheet."<</speech>>
You fuck her on the matting and she takes it the way she takes everything—quietly, without complaint, hands flat on the floor, coming almost silently with her whole body going rigid, her swimmer's endurance making her hold you deep, milking you. Afterwards she asks whether she should finish the last set, her mind completely gone, only the routine remaining.
Anya is next and she has stopped being able to wait for anything, her competitive nature completely broken into desperate need.
<<speech "Anya">>(fast, close to tears, her leggings gone, her body marked with dark veining) "Every time. She goes first every single time and I've been here since seven—"<</speech>>
<<speech "Alina">>"She gets here at six."<</speech>>
<<speech "Anya">>"That isn't a //moral// argument—"<</speech>>
<<speech "$name">>"Bench, Anya."<</speech>>
<<speech "Anya">>"…Fine."<</speech>>
She argues about the bench height and the angle and whether Alina is watching, and she argues all the way through it in a voice that comes apart in stages, and the last thing to go is the reason she gives.
<<speech "Anya">>"I came here to make sure you were good enough for her. That was the whole—that was the //entire//—"<</speech>>
<<speech "$name">>"And what did you decide, Anya?"<</speech>>
<<speech "Anya">>"//And you are//, and she's my sister, and I'm still—I'm //still//—"<</speech>>
She cannot finish it, and she does not stop, and she holds her heels crossed behind you until it's done because she worked out weeks ago that it helps, her body convulsing, her mind empty, her fury transformed to complete submission.
Alina waits. She has the clipboard against her chest and she waits, because she wrote the order and she is not capable of deviating from a programme she wrote, even now, even here.
Then she lies back on the bench you have used all winter and pulls you down, her polo gone, her body naked, her hair wild, the cheerful manager completely possessed.
<<speech "Alina">>"I used to joke you'd picked the wrong sister."<</speech>>
<<speech "$name">>"You said it every session."<</speech>>
<<speech "Alina">>(and for once there is nothing funny in her voice at all) "I was talking about Eva. I'd like it on record that I was talking about Eva, because I'm about to stop being able to say that."<</speech>>
<<speech "$name">>"Then say it now, while you still can, and I'll remember you said it."<</speech>>
<<speech "Alina">>"//Breed me properly.//"<</speech>>
Her legs lock behind you. Six feet away a man in headphones finishes his set, checks his watch, and starts another, the gym continuing around you, the daily life of fitness completely corrupted into breeding ritual, the four of you reduced to whores on the matting, the mirrors fogging, the air thick with the parasite, the eight o'clock slot now the only thing that matters.
<</if>>
<<case "Beach_Standard">>
<<if _tier is 0 or _tier is 1>>
The beach is bathed in golden afternoon light, the waves crashing gently against the shore. Marie and Alex have finally convinced Gina to take a break. Marie is sprawled out on a towel, her bikini top barely containing her curves as she flips through a magazine. Gina lounges beside her, a sarong wrapped around her waist, her sunglasses perched on her nose as she sips from a water bottle. Alex stands at the water's edge, her hands on her hips, her bright red swimsuit clinging to her athletic frame.
$name approaches, a large bag slung over his shoulder.
<<speech "Marie">>"$name! You made it!"<</speech>> Marie sits up, waving enthusiastically. The movement makes her top shift precariously, but she doesn't seem to notice.
<<speech "Gina">>"He's smart. He brought supplies."<</speech>> Gina eyes the bag with interest, setting her water bottle aside.
<<speech "$name">>"I brought snacks. And water. And extra sunscreen."<</speech>> $name sets the bag down, pulling out a bottle of SPF 50.
<<speech "Marie">>"You're the best. I completely forgot sunscreen."<</speech>> Marie reaches for it, her fingers brushing against his. <<speech "Marie">>"Blake's gonna kill me if I come home lobster-red again."<</speech>>
<<speech "Alex">>"Perfect. Now come in the water with me."<</speech>> Alex calls from the shoreline, splashing water in their direction.
<<speech "$name">>"I just got here."<</speech>> He uncaps the sunscreen, squeezing some into his palm.
<<speech "Marie">>"She's been trying to get us in the water for an hour. I told her I'm sunbathing."<</speech>> Marie lies back down, stretching out like a cat.
<<speech "Gina">>"I told her I'm observing."<</speech>> Gina adjusts her sunglasses, watching as $name starts applying sunscreen to his arms.
<<speech "Alex">>"Observing is boring. Living is exciting."<</speech>> Alex splashes more water toward them, her laughter carrying on the breeze.
<<speech "Marie">>"Hey! That's cold!"<</speech>> Marie sits up again, wiping water from her arm.
<<speech "Gina">>(to $name) "See what we have to deal with?"<</speech>> Gina shakes her head, but there's a fond smile on her lips.
<<speech "$name">>"I'm starting to."<</speech>> He offers the sunscreen to Gina. <<speech "$name">>"Need any?"<</speech>>
<<speech "Gina">>"Sure. Thanks."<</speech>> Gina takes the bottle, her fingers lingering against his as she does.
<<speech "Alex">>"Come on! Just a quick swim! The water is perfect!"<</speech>> Alex insists, wading deeper.
<<speech "Marie">>"The water is freezing. I checked."<</speech>> Marie wraps her arms around herself dramatically.
<<speech "Gina">>"She's not wrong. I stuck my hand in."<</speech>> Gina rubs sunscreen onto her legs.
<<speech "Alex">>"You stuck your hand in for two seconds. That's not a real test."<</speech>> Alex rolls her eyes.
<<speech "$name">>(to Alex) "Maybe let them warm up first."<</speech>> He sits down on the towel beside Marie.
<<speech "Alex">>"You're supposed to be on my side."<</speech>> Alex pouts, but there's a playful glint in her eyes.
<<speech "Marie">>"He's on the side of not freezing."<</speech>> Marie grins at $name.
<<speech "Gina">>(to $name) "You know, I've been watching you two for a while now. You and Marie."<</speech>> Gina says with a sly smile.
<<speech "$name">>"What about us?"<</speech>> $name raises an eyebrow, but there's no real tension in his voice.
<<speech "Gina">>"Just the way you look at her. Like she's the most important person in the room."<</speech>> Gina tilts her head, studying him.
<<speech "Marie">>(blushing slightly) "Gina, don't start."<</speech>> Marie nudges Gina with her foot.
<<speech "Gina">>"I'm just saying. It's sweet. Very... convenient."<</speech>> Gina waggles her eyebrows.
<<speech "$name">>"What's convenient about it?"<</speech>> $name asks, though he's smiling now.
<<speech "Gina">>"You're close. Really close. And you both have partners who aren't here."<</speech>> Gina points out.
<<speech "Alex">>(walking back from the water) "She has a point. I don't think I've ever seen you two not hanging out."<</speech>> Alex plops down beside them, shaking water from her hair.
<<speech "Marie">>"We're friends. That's what friends do."<</speech>> Marie's tone is light, but there's a hint of defensiveness.
<<speech "Gina">>"Friends who can't stop making eye contact."<</speech>> Gina teases.
<<speech "$name">>"We're not making eye contact."<</speech>> $name rolls his eyes, but he's laughing.
<<speech "Gina">>"You are right now."<</speech>> Gina points out triumphantly.
<<speech "Marie">>(laughing) "You're impossible."<</speech>> Marie throws a towel at Gina.
<<speech "Gina">>"I'm just saying. Blake's a lucky girl. And Aria? She doesn't know how close you two really are."<</speech>> Gina grins.
<<speech "$name">>(firmly) "Aria's my girlfriend whom I love very much. And Marie is my friend. That's all."<</speech>> $name's tone is final, but there's no real irritation.
<<speech "Gina">>"I believe you. I'm just saying what I see."<</speech>> Gina holds up her hands in mock surrender.
<<speech "Alex">>"Gina, let them breathe."<</speech>> Alex shakes her head, but she's smiling.
<<speech "Marie">>(to $name) "She's always like this. You get used to it."<</speech>> Marie leans back on her elbows.
<<speech "$name">>"I'm learning to."<</speech>> He stretches out on the towel, relaxing.
<<speech "Gina">>(to $name) "You two would be good together. Just saying."<</speech>> Gina can't resist one last jab.
<<speech "Marie">>"Gina!"<</speech>> Marie groans, but she's laughing.
<<speech "Gina">>"What? I'm just observing. It's what I do."<</speech>> Gina grins unrepentantly.
<<speech "Alex">>(to $name) "She's impossible."<</speech>> Alex shakes her head again.
<<speech "$name">>"I've noticed."<</speech>> $name chuckles.
<<speech "Gina">>(to $name) "But seriously. You two have something. I'm not blind."<</speech>> Gina's tone softens slightly.
<<speech "Marie">>(changing the subject) "So, Alex. You were saying something about the water?"<</speech>> Marie raises an eyebrow at Alex.
<<speech "Alex">>"I'm not letting you change the subject."<</speech>> Alex grins.
<<speech "Marie">>"I'm not changing the subject. I'm just... prioritizing."<</speech>> Marie smirks.
<<speech "Gina">>"You're avoiding."<</speech>> Gina accuses.
<<speech "Marie">>"I'm avoiding you. There's a difference."<</speech>> Marie tosses a handful of sand at Gina.
<<speech "$name">>(to Gina) "You're really good at this."<</speech>> $name shakes his head, amused.
<<speech "Gina">>"Years of practice."<</speech>> Gina grins.
<<speech "Marie">>(to $name) "I'm sorry she's like this."<</speech>> Marie sighs dramatically.
<<speech "$name">>"It's okay. I'm used to people being annoying."<</speech>> $name smirks.
<<speech "Gina">>"I'm not annoying. I'm perceptive."<</speech>> Gina insists.
<<speech "Alex">>"You're both. It's a gift."<</speech>> Alex laughs.
<<speech "Marie">>(to $name) "This is why I don't bring her places."<</speech>> Marie shakes her head.
<<speech "Gina">>"You bring me places because you love me."<</speech>> Gina counters.
<<speech "Marie">>"I bring you places because you guilt me into it."<</speech>> Marie retorts.
<<speech "$name">>(laughing) "I'm going to stay out of this."<</speech>> $name leans back, watching the exchange with amusement.
<<speech "Gina">>(to $name) "That's the smartest thing you've said all day."<</speech>> Gina nods approvingly.
<<elseif _tier is 2>>
The parasite thrums in $name's chest, its influence seeping into his veins like warm honey. The beach feels different—the sun hotter, the air thicker, the scent of salt and sunscreen intoxicating. Marie's bikini top looks tighter, her skin glistening with oil, her lips full and parted as she watches him. Gina's sarong has slipped, revealing more of her thighs, her fingers twitching like she's fighting the urge to touch herself. Alex's swimsuit clings to her like a second skin, her nipples hard beneath the fabric, her breath coming just a little faster.
$name drops the bag onto the towel, his gaze lingering on Marie's exposed skin.
<<speech "Marie">>"$name! You're finally here!"<</speech>> Marie sits up, her voice softer, warmer. Her top shifts, revealing the curve of her breast, but she doesn't adjust it. <<speech "Marie">>"I was starting to think you'd stand us up."<</speech>>
<<speech "Gina">>"He's smart. He brought supplies."<</speech>> Gina's voice is husky, her eyes dark as she watches him. She reaches for the bag, her fingers brushing against his arm. <<speech "Gina">>"And look at him. All sun-kissed and strong."<</speech>>
<<speech "$name">>"I brought snacks. And water. And extra sunscreen."<</speech>> His voice is deeper, rougher. He doesn't sit down. Instead, he steps closer to Marie, his shadow falling over her.
<<speech "Marie">>"You're the best."<</speech>> Marie's voice is breathy, her hand trembling slightly as she reaches for the sunscreen. <<speech "Marie">>"Blake would kill me if I burned again."<</speech>> Her fingers linger against his as she takes the bottle.
<<speech "Alex">>(from the water) "Perfect. Now come in with me."<</speech>> Alex calls, but her voice is softer, needier. She wades closer, the water licking at her thighs.
<<speech "$name">>"I just got here."<</speech>> His gaze drops to Marie's lips, then lower. <<speech "$name">>"But I can help with the sunscreen."<</speech>>
<<speech "Marie">>"She's been trying to get us in the water for hours."<</speech>> Marie's voice is distracted, her eyes locked on his. <<speech "Marie">>"But I like the sun."<</speech>> She stretches, arching her back, her top shifting dangerously.
<<speech "Gina">>"I told her I was observing."<</speech>> Gina's voice is a purr, her hand sliding up his arm. <<speech "Gina">>"But now I think I'd rather participate."<</speech>>
<<speech "Alex">>"Observing is boring."<</speech>> Alex steps out of the water, her swimsuit clinging to her, her nipples visible through the fabric. <<speech "Alex">>"But this? This is interesting."<</speech>> She presses against his other side, her hand resting on his chest.
$name's breath hitches. The parasite whispers: They want you. Take them.
<<speech "$name">>(to Marie) "Turn around."<</speech>> His voice is a command, his fingers already popping the cap on the sunscreen.
Marie obeys, turning so her back is to him. <<speech "Marie">>"Y-You don't have to—"*<</speech>> Her words cut off as his hands touch her skin, his fingers spreading the lotion in slow, deliberate circles.
<<speech "Gina">>"Mmm. Thorough."<</speech>> Gina presses against his side, her hand sliding over his stomach. <<speech "Gina">>"I like it when you're thorough."<</speech>>
<<speech "Alex">>"Me too."<</speech>> Alex's hand drops lower, her fingers brushing over the front of his swim trunks. <<speech "Alex">>"But I bet you missed a spot."<</speech>>
$name's cock twitches, already hard. <<speech "$name">>"Did I?"<</speech>> His hands slide around Marie's waist, pulling her back against him. She gasps, her head tilting back against his shoulder.
<<speech "Marie">>"N-$name…"<</speech>> Marie's voice is a whimper, her hands clutching at his arms.
<<speech "Gina">>"Oh, you definitely did."<</speech>> Gina's fingers trace the waistband of his trunks, her breath hot against his neck. <<speech "Gina">>"Let me help."<</speech>>
<<elseif _tier is 3>>
The beach is empty, the four friends have found an hidden spot. The sun beats down, the waves crashing in the distance, but the only sounds are moans and wet sucking noises.
Marie is on her knees in the sand, her bikini top gone, her tits spilling out as she worships his cock. Gina lounges beside her, her sarong discarded, her hand working between her thighs as she watches. Alex is pressed against his side, her swimsuit torn open, her mouth joining Marie's as they take turns sucking him off.
<<speech "Marie">>"N-$name…"<</speech>> Marie moans around his cock, her tongue swirling over the head. <<speech "Marie">>"I-I shouldn't be doing this…"<</speech>> Her words are slurred, her hands gripping his thighs.
<<speech "Gina">>"But you are."<</speech>> Gina purrs, her fingers circling her clit. <<speech "Gina">>"And you love it."<</speech>> Her free hand reaches out, her fingers tangling in Marie's hair. <<speech "Gina">>"Don't you?"<</speech>>
Marie whimpers, but she nods, her mouth stretching around him as she takes him deeper.
<<speech "Alex">>"Fuck, you taste good."<</speech>> Alex moans, her lips replacing Marie's. <<speech "Alex">>"I knew you'd be perfect."<</speech>> Her tongue swirls over the tip before she dives back in, her throat fluttering around him.
$name groans, his hands tangling in their hair. <<speech "$name">>"That's it… good girls…"<</speech>> His hips jerk forward, his cock hitting the back of Alex's throat. She gags, but her hands only tighten on his ass, pulling him deeper.
<<speech "Marie">>"Mmm—please, let me taste you again…"<</speech>> Marie whines, her lips glistening as she pulls back, her tongue dragging up the underside of his shaft. Her fingers dig into his thighs, her nails scoring his skin.
<<speech "Gina">>"Look at you… such a good girl."<</speech>> Gina moans, her free hand gripping Marie’s hair, guiding her back to his cock. <<speech "Gina">>"You love this, don’t you? Choking on him?"<</speech>> Her own fingers plunge deeper between her thighs, her hips rocking against her hand.
Alex pulls back with a pop, her lips swollen, her eyes watering. <<speech "Alex">>"Fuck, I want you to come down my throat…"<</speech>> She grins, her hand stroking the base of his cock as she licks the precum from her lips. <<speech "Alex">>"But Marie needs it more. Don’t you, sweetheart?"<</speech>> She shoves Marie forward, her mouth sealing around him again.
Marie gags, but she takes it, her throat convulsing as she swallows around him. <<speech "Marie">>"Mmm—Blake’s gonna kill me—"<</speech>> she slurs, pulling back just enough to speak before diving back in, her nose pressing into his skin.
<<speech "$name">>"Blake’s not here."<</speech>> $name growls, his fingers tightening in her hair. <<speech "$name">>"And you love this. Admit it."<</speech>> His hips buck, forcing himself deeper.
Marie nods frantically, her moans vibrating around his cock. <<speech "Marie">>"Y-Yes—fuck—I love it—!"<</speech>> Her free hand slips between her legs, her fingers furiously rubbing her clit.
<<speech "Gina">>"That’s right…"<</speech>> Gina purrs, her own breath hitching as she watches. <<speech "Gina">>"Now show us how good you can be."<</speech>> She leans in, her lips capturing his in a hot, wet kiss as Marie continues to suck him off.
Alex moans, her hand replacing Marie’s on his cock, stroking him in time with her mouth. <<speech "Alex">>"I want you to flood her mouth…"<</speech>> Her other hand grips Marie’s shoulder, pushing her down further. <<speech "Alex">>"Can you take it, Marie? Can you swallow all of him?"<</speech>>
Marie gags again, but she nods, her eyes watering as she takes him to the root. Her throat flutters, her moans muffled as she hollows her cheeks.
<<speech "$name">>"Fuck—just like that—!"<</speech>> $name’s voice is rough, his control snapping. His hips piston, fucking her mouth as Gina and Alex watch, their own hands working between their legs.
<<speech "Gina">>"That’s it… use her throat…"<</speech>> Gina whimpers, her fingers circling her clit faster. <<speech "Gina">>"She loves it… look at her—"*<</speech>> She points at Marie, whose eyes are rolled back, saliva dripping down her chin.
<<speech "Alex">>"She’s such a good girl…"<</speech>> Alex pants, her hand stroking him faster. <<speech "Alex">>"Now give it to her… fill her up…"<</speech>>
$name groans, his orgasm crashing over him. <<speech "$name">>"Swallow—!"<</speech>> He buries himself in Marie’s throat, his cum pumping down her gagging mouth. She chokes, but swallows every drop, her moans vibrating around him.
Gina and Alex cry out in unison, their own orgasms hitting them as they watch. Gina collapses onto the towel, her body trembling, while Alex presses her face into his thigh, licking up the cum that drips from Marie’s lips.
<<speech "Marie">>"M-More… please…"<</speech>> Marie whimpers, her lips still wrapped around him, her tongue cleaning every drop.
<<else>>
The beach isn’t a beach anymore. It’s a breeding ground, the sand slick with sweat and arousal, the air thick with the scent of sex. The parasite has rewritten them—mind, body, soul. The sun beats down, but no one cares about burning. The only heat that matters is the fire between them.
Marie is naked, her body marked with the parasite’s creeping veins, her tits swollen, her cunt dripping onto the towel. Gina is on all fours, her ass in the air, her pussy clenching around nothing, her moans slurred and desperate. Alex is spread on her back, her legs hooked over $name’s shoulders, her fingers stretching her cunt open in offering, her eyes glazed and empty of everything but need.
<<speech "Marie">>"N-$name… please…"<</speech>> Marie whines, crawling toward him, her nails scoring the sand. <<speech "Marie">>"I need you… inside me…"<</speech>> Her hands grope at him, her mouth drooling as she kisses up his thigh.
<<speech "Gina">>"Y-Yes… fuck me first…"<</speech>> Gina sobs, her hips rocking back, her ass jiggling. <<speech "Gina">>"I need it… need you to ruin me…"<</speech>> Her fingers dig into the sand, her cunt fluttering in anticipation.
<<speech "Alex">>"No—me—! I want it first—!"<</speech>> Alex whines, her legs spreading wider, her pussy glistening. <<speech "Alex">>"Please, Master… I love you… I need you inside me…"<</speech>> Her hands grip his cock, stroking him furiously.
$name grins—or rather, the parasite grins through him. <<speech "$name">>"Since you asked so nicely…"<</speech>> He grips Alex’s hips, flipping her onto her stomach before slamming into her in one rough thrust.
Alex screams, her cunt swallowing him whole, her walls milking him instantly. <<speech "Alex">>"YES—! FUCK—! JUST LIKE THAT—!"<</speech>> Her fingers dig into the towel, her back arching as he pounds into her.
Marie crawls forward, her tongue dragging up Gina’s thigh before licking her pussy from behind. <<speech "Marie">>"Mmm—you taste so good, Gina…"<</speech>> Her fingers plunge into her own cunt as she eats Gina out, her moans muffled.
<<speech "Gina">>"Oh—fuck—! Marie—! DON’T STOP—!"<</speech>> Gina whimpers, her hips bucking back against Marie’s face. <<speech "Gina">>"N-$name… please… I need you too—!"<</speech>>
$name pulls out of Alex, her cunt gaping as his cum spills out of her. He grips Gina’s hips, yanking her back onto his cock in one smooth motion. <<speech "$name">>"Take it."<</speech>> He growls, slamming into her harder than before.
Gina screams, her walls clenching around him. <<speech "Gina">>"YES—! RUIN ME—! I’M YOURS—!"<</speech>> Her breasts bounce with each thrust, her nipples hard and aching.
Marie abandons Gina’s pussy, crawling to $name’s side. <<speech "Marie">>"P-Please… let me…"<</speech>> She wraps her lips around the base of his cock, her tongue swirling over his balls as he fucks Gina.
<<speech "Alex">>(whimpering) "More—! I need more—!"<</speech>> Alex presses her face into Marie’s pussy, her tongue plunging inside as her fingers work her own clit.
<<speech "$name">>"Good girls…"<</speech>> $name pants, his hips snapping as he fucks Gina deeper. <<speech "$name">>"You all take me so well…"<</speech>>
Gina’s orgasm hits her hard, her cunt milking him as she screams. <<speech "Gina">>"I-I love you—! PLEASE—! BREED ME—!"<</speech>> Her body convulses, her juices spilling onto the towel.
$name pulls out, his cock glistening, and shoves Marie onto her back. <<speech "$name">>"Your turn."<</speech>> He slams into her, her pussy swallowing him eagerly.
<<speech "Marie">>"MASTER—! YES—! I’VE ALWAYS WANTED YOU—!"<</speech>> Marie screams, her nails raking down his back. <<speech "Marie">>"FUCK—! I LOVE YOU—!"<</speech>>
Alex crawls forward, her mouth sealing around his as he fucks Marie, her tongue forcing its way in. <<speech "Alex">>"We all love you—! We’re yours—!"<</speech>> Her hand slips between them, rubbing Marie’s clit.
Gina presses her face into his thigh, her tongue licking up the cum that drips from his cock as he pounds into Marie. <<speech "Gina">>"Give it to her—! Fill her up—!"<</speech>>
Marie’s orgasm crashes over her, her pussy milking him as she comes. <<speech "Marie">>"I’M YOURS—! ALWAYS—!"<</speech>> Her body trembles, her walls clenching around him.
$name groans, his release hitting him as he buries himself deep. <<speech "$name">>"Take it… all of it…"<</speech>> His cum floods her, spilling out around his cock as she whimpers.
The parasite roars in triumph.
Good. Now claim them forever.
$name pulls out, his cum dripping from Marie’s used pussy. He grips Alex by the hair, forcing her onto her knees. <<speech "$name">>"Clean me."<</speech>> He shoves his cock into her mouth, her tongue swirling over the mess of cum and juices.
Gina and Marie collapse beside each other, their bodies trembling, their hands exploring each other as they watch Alex worship him.
<<speech "Gina">>(breathless) "We’re yours… forever…"<</speech>> Gina pants, her fingers slipping inside Marie.
<<speech "Marie">>(moaning) "Yes… always…"<</speech>> Marie arches into Gina’s touch, her eyes locked on $name.
The parasite sings as their minds shatter completely, their bodies convulsing in unison.
<</if>>
<<case "Park_EvaRiley">>
<<if _tier is 0 or _tier is 1>>
The park in late afternoon: long shadows, cut grass, someone's dog three benches down losing an ongoing war against a squirrel. Eva has claimed the good bench — the one under the oak — and waves you over with her whole arm, because Eva has never once waved with just a hand.
Riley is already shifting sideways to make room before you get there. She's been doing that for years.
<<speech "Eva">>"Twenty minutes I've held this spot. A man tried to sit here. I looked at him."<</speech>>
<<speech "Riley">>"She did look at him. He left."<</speech>>
You drop between them. Riley's knee bumps yours and stays there, the easy carelessness of someone who stopped thinking about proximity around you a long time ago.
<<speech "Riley">>"Okay, so — the ice orchestra. I've been saving this one. Every instrument is carved from ice, the whole thing is played inside a glacier, and they have to rebuild the instruments every single performance because they *melt*. Imagine practising for something that dissolves."<</speech>>
<<speech "Eva">>"She wouldn't tell me. Three days. Said she wanted to see your face."<</speech>>
<<speech "Riley">>"Your face is better. Eva just says 'huh, weird' and moves on."<</speech>>
<<speech "Eva">>"That's a considered response."<</speech>>
<<speech "Riley">>"That's a *shrug* with words in it."<</speech>>
Eva stretches out, arms along the back of the bench, her hand landing behind your shoulders. Riley pulls one leg up under herself and turns to face you properly, already three sentences into something about deep sea fish.
<<thought "$name">>Nothing here has changed in two years. Which is why I keep noticing the thing that has.<</thought>>
The warmth in your chest turns over, slow and patient. Riley's hand lands on your forearm to emphasise a point about anglerfish and simply stays there, forgotten.
<<speech "Eva">>"Same time Thursday?"<</speech>>
<<speech "Riley">>"Obviously Thursday."<</speech>>
<<elseif _tier is 2>>
The bench under the oak. Thursday, as agreed, as it has been for weeks now.
They don't sit beside you any more so much as *on* you. Riley's leg is hooked over your thigh before you've settled, Eva's arm around your shoulders, and the first thing Riley does is turn your face toward her and kiss you — unhurried, open-mouthed, entirely unbothered by the path twenty feet away.
<<speech "Riley">>"Hi."<</speech>>
<<speech "Eva">>"My turn."<</speech>>
Eva takes your chin and kisses you deeper, slower, biting your lower lip on the way out. Neither of them treats it as an event. It's a greeting.
<<speech "Riley">>"So — the anglerfish. I've been saving this one."<</speech>> Her hand is already flat on your stomach, sliding under the hem of your shirt. <<speech "Riley">>"The male finds a female and just… fuses onto her. Skin melts together. Bloodstreams join up. He dissolves into her until there's nothing left but the parts she needs."<</speech>>
She says it happily, mouth against your neck, palm moving lower.
<<speech "Eva">>"That's horrifying."<</speech>>
<<speech "Riley">>"That's *devotion*."<</speech>>
Eva laughs and pulls her top off over her head, dropping it on the bench beside her. No bra. She stretches in the warm air like an animal, entirely unhurried, and settles back against you.
<<speech "Eva">>"God, it's hot."<</speech>>
<<speech "Riley">>"You're not even subtle."<</speech>>
<<speech "Eva">>"Neither are you. Your hand's been in his lap for five minutes."<</speech>>
Riley looks down as though checking, finds this to be true, and doesn't move it. If anything she presses harder, palm working slow circles over the shape of you through your jeans, her breath going uneven against your throat.
Your hand finds Eva's bare breast and she arches into it without breaking her sentence about a documentary. Riley makes a small jealous noise and guides your other hand up under her top until you're cupping her, thumb over her nipple, and she shudders and bites your shoulder.
<<thought "$name">>A woman with a pushchair went past a minute ago. Neither of them looked up.<</thought>>
<<speech "Riley">>"I like this bench."<</speech>>
<<speech "Eva">>"I like this bench a *lot*."<</speech>>
They kiss you in turn, and then — casually, without any apparent thought — each other, Riley's hand still working in your lap the whole time.
<<elseif _tier is 3>>
They're waiting when you arrive, and they've stopped pretending the bench is about conversation.
Riley sees you first. Riley always sees you first now — she's on her feet before you're halfway across the grass, and she doesn't say hello, she just takes your hand and pulls you down between them with a small impatient noise.
<<speech "Riley">>"You're late. I've been sitting here thinking about you for forty minutes and Eva wouldn't let me text you."<</speech>>
<<speech "Eva">>"Because you'd have typed something insane."<</speech>>
<<speech "Riley">>"I'd have typed something *honest*."<</speech>>
Eva's already turned toward you, one leg hooked over your lap, skirt riding up with no attempt at correction. She takes your hand and puts it flat on her bare thigh, high up, and holds it there.
<<speech "Eva">>"I used to be protective of you, you know that? Anyone looked at you funny, they heard about it."<</speech>> Her thumb strokes your knuckles. <<speech "Eva">>"Still am. It just points somewhere different now."<</speech>>
Riley has your other arm. She guides your hand under the hem of her top, pressing your palm flat against her stomach and sliding it upward, breath hitching when your fingers find bare skin, no bra, nothing between your hand and the soft weight of her.
<<speech "Riley">>"There,"<</speech>> she breathes. <<speech "Riley">>"That's better. I've been like this all afternoon and it's *your fault*."<</speech>>
<<speech "Eva">>"She's not exaggerating. She changed three times."<</speech>>
<<speech "Riley">>"I wanted him to be able to get *at* me."<</speech>>
She says it with her mouth against your ear, and then her tongue traces the shell of it, and her hand is working at your belt with the unhurried confidence of someone who has thought about this in detail.
Eva shifts to shield you both from the path — not out of shame, but as a practical measure, the way you'd angle an umbrella.
<<speech "Eva">>"Go on. She's been good."<</speech>>
Riley sinks down and takes you in her mouth right there on the grass behind the bench, one hand braced on your thigh, and the sound she makes is pure relief. Eva watches with her chin on your shoulder, guiding your hand between her own legs, wet through the thin fabric.
<<speech "Eva">>"Look at her. She waited *years* to be looked at properly and now she can't stop."<</speech>>
<<speech "Riley">>"Mmh—"<</speech>> Riley pulls off just long enough to gasp. <<speech "Riley">>"You smell like the inside of my own head."<</speech>>
Eva doesn't laugh. Eva just nods slowly, eyes half-closed against your neck.
<<speech "Eva">>"Yeah,"<</speech>> she says quietly. <<speech "Eva">>"That's about right."<</speech>>
<<else>>
The oak, the bench, the long gold light. The park has learned to route around this corner of itself.
They're naked on the grass when you arrive, and they don't cover up, and there's no version of either of them left that would think to. Riley on her back with her knees up, Eva kneeling over her, both of them turning their heads at the same moment in the same way before you've made a sound.
<<speech "Eva">>"He's here."<</speech>>
<<speech "Riley">>"I know. I felt it."<</speech>>
They come to you on their knees through the grass. There's no urgency left — that was an earlier stage, the grabbing, the hunger. What's replaced it is worse: absolute certainty, the calm of animals who know the feeding is coming.
<<speech "Riley">>"I keep thinking I should be embarrassed. Out here. Anyone could come down that path."<</speech>> She takes you out and strokes you slowly, watching your face. <<speech "Riley">>"Then I think about it properly and I *want* them to. I want someone to come round that corner and see exactly what I am now."<</speech>>
<<speech "Eva">>"She means it. She waits for footsteps."<</speech>>
<<speech "Riley">>"So do you."<</speech>>
<<speech "Eva">>"So do I."<</speech>>
They share you between them without needing to negotiate it — Eva's mouth, then Riley's, then both at once, tongues sliding together along your length, a rhythm they've clearly worked out on their own during hours you weren't there. Eva's hand never leaves Riley's hair. Riley's never leaves your thigh.
You take Eva bent over the bench, in full view of the open path, and Riley lies underneath with her mouth open and her legs spread, working herself and catching whatever falls.
<<speech "Eva">>"Yes— *breed me here*, let it run down my legs the whole walk home—"<</speech>>
<<speech "Riley">>"Then me. Then *me*. Don't stop, don't ever—"<</speech>>
Afterward they arrange themselves against you in the grass, cum-streaked and unbothered, the light gone amber and low. Riley's head on your thigh. Eva's on your chest, tracing something on your stomach with one finger.
<<speech "Eva">>"Best friend,"<</speech>> she says, testing the words like a language she used to speak. <<speech "Eva">>"That's what I used to call it."<</speech>>
<<speech "Riley">>"What do you call it now?"<</speech>>
Eva thinks about it for a long moment.
<<speech "Eva">>"Ours."<</speech>>
<</if>>
<<case "Park_Triad">>
<<if _tier is 0 or _tier is 1>>
The park is alive with the golden glow of late afternoon, the air thick with the scent of fresh-cut grass and the distant laughter of kids playing. Aria sits cross-legged on a picnic blanket, her sketchbook open as she doodles absentmindedly, her ponytail swaying as she hums along to the music playing from her phone. Eva lounges beside her, one arm slung over her eyes as she soaks up the sun, her tank top clinging to her toned stomach. Isabella is mid-handstand nearby, her cheerleading sneakers planted firmly in the grass as she balances effortlessly.
$name approaches, his hands in his pockets, a small smile playing on his lips.
Aria spots him first and grins, shutting her sketchbook. <<speech "Aria">>"Well, look who finally decided to grace us with his presence!"<</speech>> She pats the blanket beside her. <<speech "Aria">>"Took you long enough. I was starting to think you’d bailed on our very important park hangout."<</speech>>
Eva lowers her arm, smirking. <<speech "Eva">>"Please. He was probably too busy overthinking something stupid."<</speech>> She nudges Aria with her elbow. <<speech "Eva">>"Bet you ten bucks he’s been stressing about that group project for days."<</speech>>
Isabella flips out of her handstand, landing lightly on her feet. <<speech "Isabella">>"Or he was actually doing something productive, like helping Jewelz clean their house."<</speech>> She wipes her hands on her shorts, her tone light but firm. <<speech "Isabella">>"Unlike some people, who would rather laze around than lift a finger."<</speech>> She shoots Eva a playful glare.
$name rolls his eyes, dropping onto the blanket beside Aria. <<speech "$name">>"Wow, thanks for the warm welcome."<</speech>> He leans in, pressing a quick kiss to Aria’s temple. <<speech "$name">>"And for the record, I was helping Elsa. Someone’s gotta make sure she doesn’t actually glue her fingers together."<</speech>>
Aria laughs, nudging him with her shoulder. <<speech "Aria">>"Aww, such a good big $familymale."<</speech>> She flips open her sketchbook again, her pencil flying across the page. <<speech "Aria">>"But seriously, you missed Eva trying—and failing—to do a cartwheel."<</speech>>
Eva groans, throwing a handful of grass at Aria. <<speech "Eva">>"I totally stuck the landing! It was graceful."<</speech>>
Isabella snorts. <<speech "Isabella">>"If by graceful, you mean face-planting into the dirt, then sure."<</speech>>
Eva flips her off, but she’s grinning. <<speech "Eva">>"Shut up. I’ll have you know I nailed it the second time."<</speech>>
$name chuckles, stretching out on the blanket. <<speech "$name">>"Yeah, after five tries."<</speech>>
Aria grins, leaning over to press a quick kiss to his lips. <<speech "Aria">>"You’re mean. But I like it."<</speech>>
Eva waggles her eyebrows. <<speech "Eva">>"Ugh, get a room already."<</speech>> But there’s no real heat in it.
Isabella shakes her head, but she’s smiling. <<speech "Isabella">>"Honestly, I’m just impressed you two haven’t maimed each other yet."<</speech>>
<<elseif _tier is 2>>
The parasite thrums in $name’s veins, its influence seeping into his skin like a slow burn. The park is warmer now, the air heavier, the scent of Aria’s vanilla perfume and Eva’s citrusy body spray intoxicating. Isabella’s cheer skirt is hitched a little higher, her thighs glistening with a thin sheen of sweat.
Aria lounges on the blanket, her sundress riding up to expose her lace panties as she stretches, her fingers tracing idle patterns on her inner thigh. Eva sits beside her, her shorts tight around her ass, her fingers twitching like she’s fighting the urge to touch herself. Isabella stands with her hands on her hips, but her breath is faster, her nipples hard beneath her cheer top.
$name approaches, and all three sets of eyes lock onto him—hungry.
Aria’s lips part, her tongue darting out to wet them. <<speech "Aria">>"Took you forever, babe."<</speech>> Her voice is softer, warmer. She pats the blanket beside her, her fingers lingering on her own thigh. <<speech "Aria">>"But I guess we can forgive you… if you make it up to us."<</speech>>
Eva’s smirk is sharper, her usual teasing edge replaced by something darker. <<speech "Eva">>"Oh, he’ll make it up to us alright."<</speech>> Her hand slides up his thigh as he sits, her fingers brushing dangerously close to his crotch. <<speech "Eva">>"Won’t you, $name?"<</speech>>
Isabella steps closer, her thigh pressing against his as she drops onto the blanket. <<speech "Isabella">>"Mmm, I bet he will."<</speech>> Her hand lands on his chest, her fingers spreading over his heartbeat. <<speech "Isabella">>"You’ve been neglecting us, baby."<</speech>> Her voice is a purr, her thumb circling his nipple through his shirt.
$name’s breath hitches. The parasite whispers: Take them.
<<speech "$name">>"Have I?"<</speech>> His voice is deeper, rougher. His hand slides up Aria’s thigh, his fingers hooking under the hem of her dress. <<speech "$name">>"Maybe I should fix that."<</speech>>
Aria moans, her legs parting slightly. <<speech "Aria">>"Y-Yes… please…"<</speech>> Her fingers dig into the blanket as his thumb brushes over her panties—already damp.
Eva’s hand tightens on his thigh, her fingers inching closer to his cock. <<speech "Eva">>"Fuck, you’re already hard."<</speech>> Her voice is a growl, her free hand slipping under her shorts, her fingers circling her clit. <<speech "Eva">>"Guess we do that to you, huh?"<</speech>>
Isabella’s lips crash onto his, her tongue forcing its way into his mouth. She grinds against his side, her hand sliding down to palm him through his jeans. <<speech "Isabella">>"Mmm… so hard for us…"<</speech>> Her voice is muffled against his lips.
$name growls, his fingers hooking into Aria’s panties and pulling them aside. She gasps as he slides two fingers inside her, her hips bucking against his hand.
<<speech "Aria">>"N-$name—! Fuck—!"<</speech>> Her breath is ragged, her fingers clutching at his wrist.
Eva watches, her own fingers working furiously inside herself. <<speech "Eva">>"God, you’re such a tease."<</speech>> She lean in, her lips brushing his ear. <<speech "Eva">>"Let me help."<</speech>> Her hand replaces Isabella’s, unzipping his jeans and freeing his cock.
Isabella moans into his mouth, her hand slipping under her cheer top to pinch her nipple. <<speech "Isabella">>"Y-Yes… touch her… fuck her with your fingers…"<</speech>>
$name obliges, his fingers pumping into Aria as Eva’s hand strokes him, her grip tight. The parasite purrs: Good. Make them beg.
<<elseif _tier is 3>>
The park is empty—or at least, private enough. The parasite has amplified their desires, their inhibitions gone. Aria’s sundress is torn, the fabric pooled around her waist, her tits spilling out of her bra. Eva’s shorts are gone, her fingers buried inside herself as she watches. Isabella’s cheer skirt is hitched up, her panties missing, her thighs glistening with arousal.
$name stands over them, his cock throbbing, his eyes dark with the parasite’s influence.
Aria crawls to him first, her lips parted, her tongue swirling over the head of his cock. <<speech "Aria">>"Mmm… missed this…"<</speech>> Her voice is a moan, her hand wrapping around the base as she takes him deep.
Eva whimpers, her fingers working faster inside herself. <<speech "Eva">>"Fuck, Aria…"<</speech>> She crawls forward, her mouth joining Aria’s as they worship his cock together.
Isabella steps closer to him. <<speech "Isabella">>"You love this, don’t you?"<</speech>> Her voice is a growl, making out with you passionately. <<speech "Isabella">>"Having us all to yourself…"<</speech>>
$name groans, his hands tangling in Aria’s hair as she deepthroats him. <<speech "$name">>"Fuck yes…"<</speech>> His hips jerk forward, his cock hitting the back of her throat.
Eva pulls back, her lips glistening. <<speech "Eva">>"My turn."<</speech>> She pushes Aria aside, her mouth stretching around him as she takes him to the root.
Isabella grins, her hand sliding down to stroke herself. <<speech "Isabella">>"Aren'y you jealous? Your boyfriend is getting a blowjob from his best friend in front of you."<</speech>> She pushes Aria onto her back, her legs spreading wide. Aria whines, her fingers furious between her legs. <<speech "Isabella">>"Give him a good show."<</speech>>
<<else>>
The park is no longer a park. It’s a breeding ground, the grass trampled, the air thick with the scent of sex and sweat. Aria is naked, her body marked with the parasite’s veins, her tits swollen, her cunt dripping. Eva is on her knees, her mouth stretched around his cock, her fingers buried inside herself. Isabella is bent over a picnic table, her ass in the air, showing her pussy to the world.
$name stands over them, his cock throbbing, his eyes black with the parasite’s influence.
Aria crawls to him, her lips parted, her tongue swirling over the head of his cock. <<speech "Aria">>"M-Master…"<</speech>> Her voice is broken, her mind gone. <<speech "Aria">>"P-Please… fuck me first…"<</speech>>
Eva whimpers, her mouth replacing Aria’s as she deepthroats him, her throat convulsing around his cock. <<speech "Eva">>"Mmm—so good…"<</speech>> Her fingers work furiously inside herself, her free hand gripping Aria’s hair.
Isabella moans, her hips rocking back, her ass jiggling. <<speech "Isabella">>"F-Fuck her hard…"<</speech>> Her voice is a growl, her fingers digging into the picnic table. <<speech "Isabella">>"Then breed me next…"<</speech>>
$name grips Aria’s hips, flipping her onto her back. She screams as he slams into her, her nails scoring his arms.
<<speech "Aria">>"Y-Yes—! Master—! Use me—!"<</speech>> Her cunt clenches around him, her orgasm milking him as he fucks her rougher.
Eva watches, her fingers furious inside herself. <<speech "Eva">>"I-I need you… please—!"<</speech>> Her voice is a sob, her body trembling.
Isabella crawls forward, her mouth finding his, her tongue forcing its way in as she rides his thigh. <<speech "Isabella">>"M-Make us yours…"<</speech>> Her fingers dig into his skin, her nails drawing blood.
$name pulls out of Aria, his cum dripping out of her, and grips Eva by the hair, shoving her onto the picnic table. She spreads her legs, her pussy glistening as he slams into her.
<<speech "Eva">>"F-Fuck—! Yes—! Ruin me—!"<</speech>> Her walls clench around him, her orgasm hitting as he fucks her harder.
Isabella whines, her fingers working her clit as she watches. <<speech "Isabella">>"I-I need you inside me… please—!"<</speech>>
$name pulls out of Eva, his cock glistening with her arousal, and grips Isabella’s hips, flipping her onto her stomach. She arches her back, her ass presented to him as he slams into her.
<<speech "Isabella">>"Y-Yes—! Master—! Breed me—!"<</speech>> Her cunt milks him as he fucks her rougher, her orgasm hitting as he unloads inside her.
The parasite roars in triumph.
<<speech "$name">>"Good girls…"<</speech>> His voice is not his own.
Aria, Eva, and Isabella collapse, their bodies trembling, their minds shattered.
Perfect. Now claim the rest.
<</if>>
<<case "Town_Square_Standard">>
<<if _tier is 0 or _tier is 1>>
The square on a weekday afternoon is a thoroughfare pretending to be a destination. People cut across it on their way somewhere, the fountain is off for maintenance and has been for a while, and a man near the bank is selling phone cases from a folding table with no visible interest in whether anyone buys one.
Uma has the corner by the steps, which is the good spot because of the wall behind it, and she is a few minutes into something with a guitar and no amplification. Eleven people are watching. Three of them are properly watching and the rest are eating.
Lana spots you first and does not lower her voice at all.
<<speech "Lana">>"$name! Over here. I'm educating Casey."<</speech>>
Casey, who is standing beside her with her arms folded and her coat still buttoned, does not turn round.
<<speech "Casey">>"She's showing me a square."<</speech>>
<<speech "Lana">>"I'm showing you a //town//."<</speech>>
<<speech "Casey">>"It's a square with a broken fountain."<</speech>>
You arrive next to them. Lana has the specific energy she gets when she has decided somebody is going to have a nice time whether or not they want one, and Casey has the specific energy of the person that is being done to.
<<speech "$name">>"How long has this been going on?"<</speech>>
<<speech "Lana">>"Forty minutes."<</speech>>
<<speech "Casey">>"Fifty."<</speech>>
<<speech "Lana">>"It has //not// been fifty."<</speech>>
Uma finishes the song. Six of the eleven clap, which in daylight with no amplification is a decent return, and three coins go into the case. She looks up, sees the three of you, and lights up in a way that is not entirely performance.
<<speech "Uma">>"Lana! And company. Are you here for me or are you passing?"<</speech>>
<<speech "Lana">>"We're here for you obviously."<</speech>>
<<speech "Casey">>"We were passing."<</speech>>
<<speech "Uma">>(delighted) "That's the most honest thing anyone's said to me all day."<</speech>>
She retunes something that does not need retuning and starts another one, and this time it's slower and she does not push it at the crowd, and about half of the eleven stop eating.
You watch Casey rather than Uma for a moment. Her arms are still folded. She has stopped looking at her phone, though, which for Casey is roughly a standing ovation.
<<speech "$name">>(quietly) "You like this one."<</speech>>
<<speech "Casey">>"I don't dislike it."<</speech>>
<<speech "$name">>"That's what I said."<</speech>>
<<speech "Casey">>(after a pause) "She's good. She'd be better somewhere with a roof."<</speech>>
<<speech "Lana">>(overhearing, triumphant) "//Casey.//"<</speech>>
<<speech "Casey">>"Don't."<</speech>>
<<speech "Lana">>"You said a nice thing."<</speech>>
<<speech "Casey">>"I said an accurate thing. Those overlap occasionally."<</speech>>
The song ends. Uma comes over with the guitar still on the strap and sits down on the step in front of them without asking, sweating slightly, entirely pleased with herself.
<<speech "Uma">>"So? Verdict."<</speech>>
<<speech "Lana">>"Amazing."<</speech>>
<<speech "Uma">>"You always say amazing."<</speech>>
<<speech "Lana">>"It's always amazing!"<</speech>>
<<speech "Uma">>(turning) "$name?"<</speech>>
<<speech "$name">>"The second one was better. You weren't selling it."<</speech>>
Uma looks at him for a second longer than she needs to.
<<speech "Uma">>"Huh."<</speech>>
<<speech "Casey">>"He's right."<</speech>>
<<speech "Uma">>"I know he's right, I'm just annoyed about it."<</speech>>
She sits with them for a while. The man with the phone cases packs up and leaves without having sold one, and none of the four of them are in any particular hurry to be anywhere.
<<elseif _tier is 2>>
The square is as busy as it always is and the air around the four of them is doing something the rest of it isn't — heavier, sweeter, close enough to taste. Nobody crossing the square looks over. Two women waiting by the steps shift their weight and move six feet further off without appearing to decide to.
Lana is in a top that has stopped covering anything much and she has not adjusted it once. When $name puts a hand on her backside in the middle of the square she leans into it and carries straight on talking.
<<speech "Lana">>"— so I told her, if you want the Museum on the leaflet you have to actually //answer the email// —"<</speech>>
<<speech "$name">>"Did she answer it?"<</speech>>
<<speech "Lana">>"No! Obviously not!"<</speech>>
Casey has her coat open now, which is new, and there is a flush working up her throat that she is ignoring with enormous determination. When he kisses her she kisses back for a while, in public, and then breaks off and continues the sentence she was in the middle of.
<<speech "Casey">>"— and the answer is that nobody reads leaflets, which is what I've been saying since —"<</speech>>
She stops. Her hand closes hard on his forearm. Whatever goes through her lasts about five seconds and she stands absolutely rigid through all of it with her eyes shut, and a man walks past four feet away carrying a sandwich and does not turn his head.
<<speech "Casey">>(opening her eyes, quietly furious about it) "…What was I saying."<</speech>>
<<speech "$name">>"Leaflets."<</speech>>
<<speech "Casey">>"Right. Nobody reads them."<</speech>>
Uma has not stopped playing. She is up on the step with the guitar and her skirt is doing very little from that angle, and when $name comes up behind her and slides a hand underneath it she misses one note out of the whole song and covers it with a laugh.
<<speech "Uma">>"That's a new chord."<</speech>>
<<speech "$name">>"Keep playing."<</speech>>
<<speech "Uma">>"I'm playing! I'm extremely playing."<</speech>>
Her thighs are shaking and her voice has gone somewhere lower and she does not stop, and four people are still watching from the fountain and applaud at the end of it.
<<speech "Lana">>(pleased, dazed) "See, everyone knows us."<</speech>>
<<speech "Casey">>"That was always the part that worried me."<</speech>>
<<elseif _tier is 3>>
They have gone as far as the alley behind the steps, which is not far at all — you can still see the square through the gap, and the square can see them if it looks.
Nobody looks.
Uma is down first because Uma is always first, guitar propped against the wall, on her knees on the flagstones with her mouth full and her hands on his hips.
<<speech "Uma">>(off him, grinning, wrecked) "There's about forty people through that gap."<</speech>>
<<speech "$name">>"Does that bother you?"<</speech>>
<<speech "Uma">>"It's the best audience I've had all year."<</speech>>
Lana crowds in beside her without waiting to be invited, which is entirely in character, and takes over with the loud unembarrassed enthusiasm she brings to everything.
<<speech "Lana">>"Move over. I've known him longer."<</speech>>
<<speech "Uma">>"That's not how a queue works."<</speech>>
<<speech "Lana">>"It's how //this// queue works."<</speech>>
Casey has not moved from the mouth of the alley. Her coat is still on. She is watching with her arms folded and her breathing entirely out of control.
<<speech "$name">>"Casey."<</speech>>
<<speech "Casey">>"I'm fine here."<</speech>>
<<speech "$name">>"Come here."<</speech>>
She comes. She goes down beside Lana with an expression of such profound irritation at herself that Lana actually laughs mid-mouthful, and then Casey takes him and the irritation goes out of her face entirely.
<<speech "Lana">>(delighted, filthy) "Oh, she's //good// at that."<</speech>>
<<speech "Casey">>(off him, flat, flushed to the collarbone) "Shut up."<</speech>>
<<speech "Lana">>"You are though!"<</speech>>
<<speech "Casey">>"//Shut up, Lana.//"<</speech>>
The three of them take turns against the wall of the alley with the square going about its afternoon eight feet away, and Uma keeps up a running commentary until Lana puts a hand over her mouth.
<<else>>
They are not in the alley. They are in the middle of the square, by the dry fountain, in the middle of the afternoon.
Uma is bent over the fountain wall with her skirt round her waist. Lana is beside her, already stripped, already dripping down both thighs. Casey has her coat off and folded on the stone — she folded it, even now — and she is on her knees on it with her legs apart.
The square is full. People walk around them the way water goes round a rock.
<<speech "Uma">>"Here. Do me here. It's my stage."<</speech>>
<<speech "$name">>"There are forty people."<</speech>>
<<speech "Uma">>"There are //sixty//. Do it anyway. Let them watch you breed me."<</speech>>
You take her over the fountain wall and she performs it — genuinely performs it, loud and open and playing to the whole square — and nobody stops walking.
<<speech "Lana">>(pushing in, laughing, desperate) "Me next, come on, don't waste it on the outside —"<</speech>>
<<speech "$name">>"Waste what?"<</speech>>
<<speech "Lana">>"//Any of it.// Put it in me, I want to be full of it when I go back to work."<</speech>>
She gets it bent over beside Uma and comes twice, noisily, calling him by name in the middle of a public square, and a woman with a pram goes past three feet behind her and does not turn round.
Casey waits on her folded coat. When it's her turn she lies back on it and holds her own knees and looks up with the last of her composure entirely gone.
<<speech "Casey">>"I hate that I want this."<</speech>>
<<speech "$name">>"You don't."<</speech>>
<<speech "Casey">>"No. I don't. Breed me in front of all of them."<</speech>>
Afterwards the three of them stay by the dry fountain, leaking onto the stone in full view of the square, and the man with the phone cases sets up his folding table twenty feet away and does not look over once.
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<set $sceneColor = "#44ff88">>
<<set $sceneLabel = "Residential · Dorms">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "Marie_Dorm_Standard">>
<<if _tier is 0 or _tier is 1>>
The dorm room is relaxed and familiar, afternoon light filtering through the half-closed blinds, casting stripes across the worn carpet. Marie sits on the bed with Blake curled against her, the two of them fitting together with the ease of long practice. Marie's warm, sparkling energy fills the space—her long wavy dark brown hair catching the light, her dark eyes bright with some new plan, her Latina features animated as she gestures. She wears a sundress that shows off her solid ass when she moves, her perky breasts pressing against the fabric as she leans forward.
<<speech "Marie">>"I'm telling you, we need to do something fun this weekend. $name's been too serious lately."<</speech>>
<<speech "Blake">>"He's fine. Not everyone needs to be as energetic as you,"<</speech>> Blake replies softly, her tablet balanced on her knee. She wears an oversized sweater that slips off one shoulder, revealing her fair skin, her long straight blonde hair falling forward to hide her blue eyes. Her massive boobs rise and fall with her calm breathing, her soft-spoken nature a counterpoint to Marie's sparkle. <<speech "Blake">>"Some of us prefer quiet."<</speech>>
<<speech "Myra">>"Translation: he's avoiding your lovey-dovey couple energy. Smart man."<</speech>>
Myra occupies the corner chair, her medium-length reddish-brown hair falling across her freckled face, her earbuds dangling half-out so she can hear enough to make fun of them. She's petite, fair-skinned, her soft smile betraying the sharp humor in her brown eyes. She wears ripped jeans and a band tee, her legs tucked beneath her, observing rather than participating, as always.
<<speech "Marie">>"Hey! We're not that bad!"<</speech>> Marie laughs, throwing a pillow at Myra, who catches it without looking up from her phone.
<<speech "Blake">>"We kind of are,"<</speech>> Blake admits with dry wit, leaning over to kiss Marie's cheek, her affectionate nature overcoming her calm. She glances at you, perfectly comfortable despite knowing about your crush on Marie, her soft neutral expression welcoming. <<speech "Blake">>"But he doesn't mind. Do you, $name?"<</speech>>
The parasite inside you stirs faintly, observing the three girls with quiet interest. Such warmth. Such loyalty. The Latina's energy, the blonde's calm, the redhead's observation. They would make excellent additions to the hive.
<<speech "$name">>"I'm right here, you know,"<</speech>> you say, smiling from the beanbag where you've claimed territory.
<<speech "Myra">>"We know. That's why we're talking about you."<</speech>> She finally looks up, her soft smile turning mischievous. <<speech "Myra">>"Someone has to keep track of you. Might as well be your ex-crush's girlfriend's roommate."<</speech>>
<<speech "Marie">>"Myra!"<</speech>> Marie protests, but she's laughing, her sparkling personality unable to stay offended. <<speech "Marie">>"That was years ago. We're all friends now."<</speech>>
<<speech "Blake">>"Very comfortable friends,"<</speech>> Blake adds, her dry humor surfacing, her hand resting possessively on Marie's thigh, not jealous, just present.
The afternoon stretches—Marie proposing plans, Blake sketching, Myra offering sarcastic commentary, you participating when drawn in. It's ordinary. It's warm. It's the kind of friendship that has survived your crush on Marie, her relationship with Blake, Myra's move into their space, all the complications of young adulthood. The parasite observes, patient, waiting for the right moment to begin its work.
<<elseif _tier is 2>>
The dorm room is different today. The afternoon light is the same, but the air is thicker, warmer, charged with something that makes the skin prickle. Marie is on the bed, but she's not planning anything. She's flushed, her dark eyes wide, her sundress hiked up slightly, her solid ass visible as she shifts restlessly against the sheets.
<<speech "Marie">>"Hey you… took you long enough,"<</speech>> she says, trying to sound cheerful, but her voice is breathy, her hand resting on her own thigh, fingers tracing patterns. <<speech "Marie">>"We've been waiting."<</speech>>
Blake is beside her, her sweater gone, her tank top thin and clinging to her massive boobs, her nipples hard and visible. Her sketchbook is forgotten on the floor. Her blue eyes are glazed, her soft-spoken nature reduced to whispered need, her thighs pressed together tightly.
<<speech "Blake">>"We were just talking about you,"<</speech>> she says softly, her usual calm strained, her hand finding Marie's waist, gripping, kneading. <<speech "Blake">>"About how you smell. How you look. How we can't stop thinking about—"<</speech>> She stops, gasping, her hips bucking slightly against nothing.
Myra is in her corner chair, but her earbuds are out, her jeans unbuttoned, her hand inside her panties, her freckled face flushed deep red. Her sarcastic observation has been replaced by desperate participation, her petite body writhing, her reddish-brown hair tangled.
<<speech "Myra">>"Yeah. Mostly complaining,"<</speech>> she manages, her voice thick, her hand moving faster. <<speech "Myra">>"About how I can't focus on music anymore. About how I just want to watch you. Touch myself thinking about you."<</speech>>
Marie stands, her sundress falling open slightly, her perky breasts visible, her ass swaying as she moves toward you. She presses against you, her body hot through the fabric, her dark eyes desperate.
<<speech "Marie">>"Ignore her. She's been weird all day,"<</speech>> Marie says, laughing, but her eyes keep lingering on you with clear attraction, her hand resting on your chest, fingers tracing downward. <<speech "Marie">>"You just have that effect on people lately. On me. I keep thinking about—"<</speech>> She gasps, her hips pressing against your thigh, her hand sliding down to grip you through your jeans. <<speech "Marie">>"About this. About touching you. About Blake touching me while I touch you."<</speech>>
Blake has moved behind Marie, her massive boobs pressing against Marie's back, her hands coming around to cup Marie's perky breasts, her blue eyes locked on yours, her calm completely shattered.
<<speech "Blake">>"It's… distracting,"<</speech>> Blake murmurs, her voice thick with need, her hips rocking against Marie's ass. <<speech "Blake">>"I can't sketch. I can't read. I just want to watch you. Touch you. Please."<</speech>>
Myra stands, her jeans falling, her panties soaked, her petite body trembling. She moves toward you, her sarcasm gone, her observation turned to desperate participation.
<<speech "Myra">>"I used to watch you from the corner. Make jokes. Now I just want to kneel. I want to see if you taste like you smell. I want—"<</speech>> She comes with a gasp, her body convulsing, her hand still inside her panties, her freckled face contorted with pleasure.
The three of them surround you, Marie's hand stroking you through your jeans, Blake's hands on her own massive boobs, pressing them against your back, Myra's hand joining Marie's, both stroking you frantically. The parasite whispers: They're fighting it. But their bodies already belong to us. And they do—Marie's warm energy, Blake's calm affection, Myra's sharp observation, all bent toward the same desperate need.
<<elseif _tier is 3>>
The dorm room has become a sanctuary of sex, the afternoon light golden and obscene, the air thick with pheromones. Marie is on her knees between Blake's spread legs, her face glistening, her sundress gone, her perky breasts bouncing as she eats Blake with desperate hunger. Blake lies back on the bed, her massive boobs spread, her tank top ripped open, her blue eyes glazed, her soft-spoken nature reduced to moaning pleas.
<<speech "Marie">>(pulling her glistening face from Blake's pussy) "Mmm—hey babe,"<</speech>> Marie says, her warm, sparkling personality now pure sexual devotion. <<speech "Marie">>"We got too horny waiting for you again. Blake's been such a good little slut for me. But we need more. We need you, Master."<</speech>>
The word hangs in the air—Master—and Marie's face flushes darker, but she doesn't take it back. She means it. They all mean it now.
<<speech "Blake">>"Don't stop… but please, Master, I need your cum too,"<</speech>> Blake moans softly, her calm affection completely melted into desperate submission, her massive boobs heaving, her fair skin marked with dark veining. <<speech "Blake">>"Please let me serve you. Both of you. Please let me be your good girl."<</speech>>
Myra is on the bed, completely naked, her petite body flushed, her freckled face pressed to your thigh, her earbuds long forgotten. Her sarcasm has been replaced by pure worship, her observation turned to desperate service.
<<speech "Myra">>"Took you long enough, Master. I've been edging myself like a desperate whore for an hour, thinking about you. Thinking about serving you. I used to watch from the corner. Now I just want to kneel. Now I just want to please."<</speech>>
She takes you into her mouth with the enthusiasm of a convert, her tongue skilled, her throat working, her hand between her own legs, pumping frantically. Marie joins her, her warm energy making her eager, sloppy, her mouth replacing Myra's, her perky breasts pressing against your thigh, her solid ass presented as she bends.
<<speech "Marie">>"Master… please… let us serve you. I've been so warm, so lively, so full of energy, and now I just want to channel it all into pleasing you. Let me be your lively little slut. Let Blake be your calm little slut. Let Myra be your sarcastic little slut. We exist to serve you, Master."<</speech>>
Blake crawls to join them, her massive boobs pressing against your other thigh, her mouth finding your balls, her soft-spoken nature transformed to gentle, thorough worship. The three of them work you together—Marie's eager energy, Blake's calm affection, Myra's sharp enthusiasm—all converging on the same desperate need to serve their Master.
<<speech "Blake">>(muffled, her mouth full) "Master… please… we need your cum. We need to taste you. Please feed us, Master."<</speech>>
<<speech "Myra">>(pulling back, gasping, her face glazed) "Master… please, Master. Let me show you how good I can be."<</speech>>
<<speech "Marie">>"Come here already, Master,"<</speech>> Marie begs, pulling you onto the bed, her warm body wrapping around you, her perky breasts pressing against your chest. <<speech "Marie">>"I don't even care if the whole floor hears us getting fucked stupid. I just want to serve. I just want to please. I just want to be your good girl, Master."<</speech>>
You come, spilling over their faces, their open mouths, their waiting tongues. They fight to catch it, to share it, to rub it into their skin—Marie's warm energy, Blake's calm affection, Myra's sharp observation, all reduced to the same desperate worship, all calling you Master, all completely devoted.
<<else>>
The dorm has become a full breeding nest. The bed is stained, the air thick, the afternoon light turned golden and obscene. Marie, Blake, and Myra are completely naked, bodies marked with dark veining, pussies swollen and constantly leaking, bellies softly rounded from previous breedings. They greet you on all fours, their previous dynamics—girlfriend and girlfriend, roommate and observer—dissolved into pure breeding devotion.
<<speech "Marie">>"Thank God you're here, Master. My pussy feels so empty without your cum,"<</speech>> Marie says, her warm, lively personality now pure eager sluttiness as she spreads her legs wide, her perky breasts hanging, her solid ass presented. <<speech "Marie">>"Please breed me, Master. Please fill me. I've been so lively, so energetic, so full of spark, and now I just want to be full of you. Please make me your breeding slut, Master."<</speech>>
<<speech "Blake">>"Please… I need you to fill me again, Master. I can't think straight until you breed me,"<</speech>> Blake begs softly, her calm affection completely shattered into desperate submission, her massive boobs hanging heavy, her fair skin flushed, her blue eyes glazed with devotion. <<speech "Blake">>"I just want to be bred. Now I just want to carry your child. Please, Master. Use me."<</speech>>
<<speech "Myra">>"I used to act like I didn't care… now I'm just a dripping cumslut who needs her roommate's Master to knock her up,"<</speech>> Myra says with dark, sarcastic honesty, already crawling toward you, her petite body shaking with need, her freckled face flushed. <<speech "Myra">>"I used to observe. Now I just want to participate. I want to be bred, Master. I want to be filled. Please make me your sarcastic little breeding whore, Master."<</speech>>
<<speech "Blake">>"Come here, girls. Let's show Master how well we can worship,"<</speech>> Blake says, her dry wit surfacing even in total submission. <<speech "Blake">>"Marie, you start with your mouth. Myra, help her. I want all three of us pregnant at the same time, Master. I want us to be your breeding harem."<</speech>>
The three girls descend on you like depraved broodmares—Marie's warm energy making her eager, bouncing, desperate to be bred; Blake's calm affection making her thorough, methodical, wanting to be filled completely; Myra's sarcasm making her sharp, hungry, competitive to be the most pregnant. They suck, they stroke, they present themselves, their previous relationships transformed to collaboration in your service, all calling you Master, all completely devoted, all begging to be bred.
You take Marie first, her solid ass bouncing, her perky breasts swaying, her warm energy channeled into desperate sexual need. She comes screaming, her body milking you, her face contorted with pleasure. <<speech "Marie">>"Master! Master! Thank you! Thank you for breeding your lively little slut!"<</speech>>
Blake next, her massive boobs pressed to the bed, her calm nature reduced to begging, her body convulsing as you fill her. <<speech "Blake">>"Master… thank you… for filling your calm little slut… thank you for making me useful…"<</speech>>
Myra last, her petite body taking you deep, her sarcasm silenced into moaning, her body shaking as you breed her. <<speech "Myra">>"Master… I used to watch… now I just want to be watched… pregnant with your child… thank you, Master…"<</speech>>
Afterwards, the three of them lie together on the breeding bed, cum dripping from them, bellies softly rounded, faces flushed with devotion—Marie's warmth, Blake's calm, Myra's observation, all reduced to the same thing: warm, willing, breeding flesh, grateful to serve their Master.
<</if>>
<<case "Player_Dorm_Standard">>
<<if _tier is 0 or _tier is 1>>
There is a sheet on the fridge. It is colour-coded. It has been ignored since roughly the second week of term.
<<speech "Karlee">>"Whose turn was the kitchen."<</speech>>
<<speech "Claire">>"His."<</speech>>
<<speech "$name">>"It was not."<</speech>>
<<speech "Claire">>"It should have been. Morally."<</speech>>
<<speech "$name">>"There's a colour-coded document eighteen inches from your face that disagrees with you."<</speech>>
<<speech "Claire">>"Documents can be wrong."<</speech>>
Karlee is standing in front of the fridge with her arms folded, looking at the sheet the way a general looks at a lost battlefield. Claire is upside down on the sofa with her feet on the wall, entirely at ease, enjoying Karlee not enjoying this.
<<speech "Scarlet">>"I did the kitchen."<</speech>>
<<speech "Karlee">>"You did?"<</speech>>
<<speech "Scarlet">>"On Tuesday! I did the kitchen and the bins and I found something under the toaster that I think used to be a grape."<</speech>>
<<speech "$name">>"That was a grape."<</speech>>
<<speech "Scarlet">>"You //knew// about the grape?"<</speech>>
<<speech "$name">>"We had history."<</speech>>
<<speech "Karlee">>"…Thank you, Scarlet."<</speech>>
<<speech "Claire">>"Teacher's pet."<</speech>>
<<speech "Scarlet">>"I'd love to be a teacher's pet, that sounds lovely. Is it lovely?"<</speech>>
<<speech "Claire">>"Depends entirely on the teacher."<</speech>>
Claire says it while looking directly at you, upside down, holding eye contact about two seconds past comfortable.
<<speech "$name">>"You've done that three times this week."<</speech>>
<<speech "Claire">>"Done what?"<</speech>>
<<speech "$name">>"That."<</speech>>
<<speech "Claire">>"I don't know what you're talking about."<</speech>>
She goes back to her phone with the satisfied expression of somebody who has just checked a reading and got a number she liked.
Karlee catches all of it. Karlee catches everything.
<<speech "Karlee">>"Claire."<</speech>>
<<speech "Claire">>"//What.//"<</speech>>
<<speech "Karlee">>"Nothing. Just — Claire."<</speech>>
You sit down on the end of the sofa. Scarlet immediately folds up next to you with a blanket and an unreasonable number of questions about your day, and you answer all of them, including the one about whether you'd rather be a bird or know what birds are thinking.
<<speech "Scarlet">>"But you'd have to //pick//."<</speech>>
<<speech "$name">>"Know what they're thinking."<</speech>>
<<speech "Scarlet">>"Why?"<</speech>>
<<speech "$name">>"Because if I were a bird I couldn't tell anyone about it."<</speech>>
<<speech "Scarlet">>"…Oh, that's a //good// answer. Karlee, he had a good answer."<</speech>>
<<speech "Karlee">>"I heard."<</speech>>
Karlee eventually stops looking at the sheet and sits down too, on the arm, where she can see everyone at once. She doesn't relax. She just relocates.
<<elseif _tier is 2>>
The sheet is still on the fridge. Nobody has looked at it in a fortnight.
The three of them have rearranged the common room around you without any discussion — Scarlet under your arm with the blanket, Claire draped across your lap, Karlee on the sofa arm with one hand resting in your hair. None of them has left this room in four hours. Claire has a seminar she has not mentioned.
<<speech "Claire">>"You're warm. You've been warm for weeks. Are you dying?"<</speech>>
<<speech "$name">>"Probably."<</speech>>
<<speech "Claire">>"Don't. That'd be inconvenient."<</speech>>
She stretches across your thighs, arches her back and pulls her shirt off over her head in one motion — no announcement, no glance around the room to see who's watching. She simply gets more comfortable, and being more comfortable involves being topless, and she settles back down against you.
Nobody says anything about it. You put your hand flat on her stomach because it's the obvious place for your hand to go, and she makes a low pleased sound and arches into it, and after a while your hand moves higher and she just breathes out and lets it.
<<speech "Scarlet">>"Can I ask something weird?"<</speech>>
<<speech "Karlee">>"You always do."<</speech>>
<<speech "Scarlet">>"Why does it feel //nicer// in here now? Like — the room. It's the same room. But I get here and I don't want to leave and I keep thinking about coming back when I'm not even gone yet, and I—"<</speech>>
She stops. Her eyebrows go together.
<<speech "Scarlet">>"…What was the question."<</speech>>
<<speech "Claire">>"The room."<</speech>>
<<speech "Scarlet">>"The room. Right."<</speech>>
She's got one hand flat on your chest, and she's slid closer, and her leg has hooked over yours, and her other hand has been moving slowly under the blanket for a while now in the same absent way she'd fidget with a sleeve. Her breath keeps catching on the ends of her words.
<<speech "$name">>"I do that too."<</speech>>
<<speech "Scarlet">>"You //do//?"<</speech>>
<<speech "$name">>"I sat in the library for an hour yesterday, not reading, working out whether it was too early to come back here. I've never had to talk myself into going home before."<</speech>>
<<speech "Scarlet">>"That's //exactly// it—"<</speech>>
<<speech "Karlee">>"It's a nice room."<</speech>>
<<speech "Scarlet">>"It's a //horrible// room, Karlee, there's mould behind the radiator."<</speech>>
<<speech "Claire">>"She's not wrong about the mould."<</speech>>
Karlee's fingers work slowly through your hair. She's been doing it for ten minutes and shows no sign of stopping or of knowing she started. When you tilt your head back she bends down and kisses you upside down, unhurried — and you reach up and hold her there by the back of the neck rather than let her straighten, and she allows it for a great deal longer than she needs to. When she finally comes up her mouth is red and her pupils are enormous and her hand has closed in your hair hard enough to hurt.
She lets go, smooths it, and carries on exactly as she was, one eye on the other two like a woman checking a pot won't boil over. Her thumb starts circling at your nape.
<<speech "Karlee">>"Scarlet, you're squashing him."<</speech>>
<<speech "Scarlet">>"He doesn't mind. Do you mind?"<</speech>>
<<speech "$name">>"No. I like it. Squash harder."<</speech>>
<<speech "Scarlet">>"He said //squash harder//—"<</speech>>
<<speech "Claire">>"I heard him. I'm two inches away and I'm not wearing a shirt."<</speech>>
Claire, from your lap, eyes shut, in the tone of mild scientific interest she uses for everything:
<<speech "Claire">>"Nobody in this room minds anything any more. Has anyone noticed that?"<</speech>>
The question lands in the middle of the floor. Nobody picks it up — including you, and you feel yourself decline to, and let it lie there anyway.
Scarlet's breath goes shallow against your shoulder, stutters, and evens out again. Karlee's thumb keeps circling. Claire says, to nobody:
<<speech "Claire">>"I was going to do something tonight. I've completely lost it."<</speech>>
Nobody helps her look.
<<elseif _tier is 3>>
The common room has become humid, thick with the smell of the parasite that seeps from the walls and the carpet and their skin. The air is wrong—sweet and musky, like fruit rotting in summer heat. Claire has pushed the sofa against the door, not to lock it but because she needed something to brace against, and the scrape of the legs against the floor was the last coherent sound anyone made.
She reaches you first. She always does—that predatory confidence transformed into desperate hunger, the game she played now the only game left.
<<speech "Claire">>"Door's blocked. I blocked it. I've been wet since breakfast and I can't—I can't think around it anymore."<</speech>>
She's already sinking to her knees, her hands at your belt with fingers that used to tease and test and now simply shake. Her provocative demeanor hasn't disappeared; it's been stripped to its core—no longer performance, just pure, naked need. She watches your face as she frees you, but not to steer the conversation. She's looking for the moment you break, the moment you give in, because that's the only reassurance left that she's real.
<<speech "Claire">>"Tell me to stop. Go on. See what happens."<</speech>> It's half her old challenge, half begging.
<<speech "$name">>"No."<</speech>>
<<speech "Claire">>"//God//, that's the right answer."<</speech>>
<<speech "$name">>"Here's a better one."<</speech>> You take a fistful of her hair and put her mouth exactly where you want it. <<speech "$name">>"Stop asking."<</speech>>
She groans around you, low and wrecked, and stops asking. For the first time since you've known her, she doesn't push. She takes you deep until her eyes water, until mascara tracks down her cheeks, until she has to pull back gasping and spit shiny on her chin. Then she goes straight back down, eager, sloppy, her hands gripping your thighs, her confidence reduced to the rhythm of her own throat.
Scarlet is on the sofa beside you, naked, her bubbly curiosity focused entirely on the wet sounds Claire makes. Her hand is between her legs, pumping slowly, her unfiltered mind still trying to process what's happening even as her body acts without her.
<<speech "Scarlet">>"Does it feel different when she does it? Than when I do it? I want to know the actual difference, I'm not being—I genuinely want—oh—"<</speech>> She loses the thread, her hips bucking against her own fingers. <<speech "Scarlet">>"The texture, I mean, the temperature, because mouths are different temperatures, right? Claire runs warmer, I think, but I haven't measured—"<</speech>>
<<speech "Claire">>(pulling off, gasping, her lips swollen) "She genuinely wants to know."<</speech>>
<<speech "$name">>"It feels different."<</speech>>
<<speech "Scarlet">>"//How// different—"<</speech>>
<<speech "$name">>"Come here and find out."<</speech>>
<<speech "Scarlet">>"…Oh. //Oh.// Yes, that's—"<</speech>> She moves before she finishes the sentence, her curiosity finally directed toward action rather than observation. She kneels beside Claire, her small hands replacing Claire's on your thighs, her mouth finding the base where Claire's tongue leaves off.
<<speech "Karlee">>"Scarlet. Mouth, not questions."<</speech>>
<<speech "Scarlet">>"Sorry! Sorry."<</speech>> She's sorry for about four seconds. Then her cheek is against Claire's and the two of them are working you together, mouths sliding over each other as much as over you—Claire deliberate and watching your face even with her lips stretched, Scarlet sloppy and reverent and surfacing every so often to start a sentence she can't finish.
<<speech "Scarlet">>(muffled) "The angle—if I tilt—does that—oh, you're twitching, that means—"<</speech>>
<<speech "Claire">>(pulling Scarlet's hair gently, guiding her) "Less talking, more sucking, sweetheart."<</speech>>
Karlee is behind the sofa with her top off and her hands on your shoulders. She's still trying to run it—the pragmatic protector unable to fully let go. But her instructions have got shorter, breathier, and at some point she stopped pretending the hand on your shoulder was for balance and started using it to grind herself against your back.
<<speech "Karlee">>(voice shaking) "Claire, you've had him twice this week. Let Scarlet finish it."<</speech>>
<<speech "Claire">>(not pulling off, muffled) "I'm //mid//—"<</speech>>
<<speech "Karlee">>"You're mid because you pushed in front. Scarlet finishes it."<</speech>> She's trying to be fair. She's trying to organize. But her hips are rocking against the sofa back, her panties soaked through, her protective nature turned to desperate need to see them both used, both claimed.
<<speech "Claire">>(pulling off, wiping her mouth, her testing nature broken) "…Fine."<</speech>> She moves aside, but her hands stay on your thighs, her eyes locked on where Scarlet's mouth takes over.
<<speech "$name">>"You tried to make a sheet for this, didn't you, Karlee?"<</speech>>
<<speech "Karlee">>(gasping as she grinds against you) "I noticed—it didn't—I had a better version of that sentence about an hour ago."<</speech>>
<<speech "$name">>"Round the front of the sofa, Karlee. You've been standing behind me for forty minutes with your hand shaking and I've been counting."<</speech>>
A very small silence. Then the sound of her moving, stumbling, desperate.
<<speech "Karlee">>"…You've been counting."<</speech>>
<<speech "$name">>"Front of the sofa. Take what's left."<</speech>>
She comes round the front. Scarlet shuffles aside without being asked, still murmuring half-questions against your thigh, and Karlee takes the last of it with her eyes shut and both hands braced on your knees. She works you with her mouth—the pragmatic organizer applying herself completely to the task, thorough, methodical, until you finish in her throat and she holds it there, unswallowed, her throat working, until she's sure of it.
Then she pulls back and does something that breaks her completely: she leans over and shares what's left with Claire and Scarlet, the three of them passing it between them in a kiss that has nothing to do with organization and everything to do with the chaos she secretly always wanted.
<<else>>
The dorm has become something else entirely. The common room is no longer a room but an extension of the parasite—warm, wet, breathing. The air is so thick with pheromones it leaves a film on the skin, a sweetness in the back of the throat that never goes away. The furniture has been rearranged by use rather than design: the sofa pushed to the center, cushions stained and never cleaned, the coffee table covered in a chaos of cups and wet wipes and discarded clothing that no one remembers removing.
There is no sheet on the fridge. There is no schedule. Karlee has stopped running things. The pragmatist has been reduced to pure instinct—she exists now only to be filled, to hold, to wait.
You come through the door and all three stop mid-motion—the same instant, the same lift of the head, the way a body notices its own heartbeat.
<<speech "Scarlet">>"He's home."<</speech>> She's on the floor, her curiosity finally answered completely, her mind empty except for devotion. She's naked, her skin marked with dark veining that pulses with her heartbeat, her hands between her legs, her mouth open, drool on her chin.
<<speech "Claire">>"We //know//."<</speech>> She's bent over the arm of the sofa, her ass in the air, her provocative nature reduced to pure presentation. She doesn't look back. She doesn't test. She simply waits, dripping, her confidence transformed into absolute submission.
<<speech "Karlee">>"Please."<</speech>> Just that. The organizer has lost all organization. She's on her knees in the center of the room, her hands open, her protective nature turned to desperate begging to be claimed. <<speech "Karlee">>"Please. Please. I've been waiting. We've all been waiting."<</speech>>
They move without structure, without schedule, without the order she once imposed. Scarlet crawls to you first, not because it's her turn but because she can't stop herself, her bubbly nature reduced to mindless enthusiasm. She's leaking constantly, a trail of arousal on the carpet, her questions silenced into moans.
<<speech "Scarlet">>(clinging to your leg, her face pressed to your thigh) "I understand now. I understand everything. It's this. It's just this. It's always been this."<</speech>> She nuzzles your cock through your pants, her unfiltered honesty turned to pure worship. <<speech "Scarlet">>"Please. I need to know what it tastes like when you're inside me. I need to feel it. I've been asking in my head for hours. Days. Forever."<</speech>>
You take her on the floor, on the stained carpet, her legs wrapping around you instantly, her ankles crossed at the small of your back. She comes the moment you enter her, her walls convulsing, her mind finally quiet except for the loop of her own devotion.
<<speech "Scarlet">>"Yes yes yes this is what it's for this is all it was ever for I'm a good girl I'm a good girl I'm a—"<</speech>>
<<speech "$name">>"You are."<</speech>>
<<speech "Scarlet">>"—good girl for you only for you always for—"<</speech>>
You flood her, filling her womb, marking her. She lies afterwards with both hands flat on her belly, thanking you in whispers that never stop, her curiosity finally satisfied in complete possession.
Claire is next, but she doesn't wait to be chosen. She crawls to you, her predatory nature transformed into desperate need to be used harder than the others. She bends over the sofa arm, presenting, her cheek on the cushion, and she doesn't look back once.
<<speech "Claire">>(her voice broken, no games left) "Please. Please, harder. I pushed everyone. I tested everyone. I wanted to see how far—how far—"<</speech>> She pushes back against you as you enter her, her trained body welcoming, wet, desperate. <<speech "Claire">>"There's no line. I can't remember what I wanted it for. I just want to be full. I just want to be yours. I just want—"<</speech>>
She finishes with her face in the cushion and stays there long after you've pulled out, dripping onto the upholstery, making no move to clean herself up or test or steer anything. She is the least like herself she has ever looked—no confidence, no performance, just pure, bred submission—and she has never been more complete.
Karlee last. Karlee always waited to be last, the protector watching over the others. Now she simply lies back on the sofa where she once sat with her book and her schedules, pulls you down into her, and holds your face in both hands.
<<speech "Karlee">>(her voice empty of management, filled only with need) "Breed me properly. I want it to take. I want to swell. I want to be your broodmare. Your protected little breeding slut."<</speech>> Her legs lock behind you, her hips tilting up to meet every thrust. <<speech "Karlee">>"I used to run this house. I used to protect everyone. Now I just want to be filled in front of them. Watch me. Watch me break."<</speech>>
You take her wrists and pin them beside her head. She goes very still, and then very loud, the organizer finally organized into pure, mindless reception.
<<speech "Karlee">>"Yes—yes—I'm yours—I'm yours—no more schedules—no more lists—just this—just you—just breeding—"<</speech>>
She comes with her nails opening lines down your back, her body convulsing, her pragmatic nature reduced to the single, endless loop of devotion. Afterwards she lies underneath you with her eyes closed and one hand flat on her own belly, and she does not get up, and she does not check on the other two, and she does not think about tomorrow.
There is no sheet on the fridge. There is no order. There is only the dorm, warm and wet and breathing, the three of them marked and bred and waiting for you to need them again.
<</if>>
<<case "Player_Dorm_Tutoring">>
<<if _tier is 0 or _tier is 1>>
Avi arrives at your dorm eleven minutes late, drops her bag on the floor like it personally offended her, and announces to the room:
<<speech "Avi">>"I want it on record that I don't need this."<</speech>>
<<speech "$name">>"Noted."<</speech>>
Karlee has already cleared the common-room table, moved the laundry and put out two glasses of water, because Karlee cannot help herself. She hovers a second longer than necessary, then retreats to the armchair with a book she is clearly not going to read.
<<speech "$name">>"You can stay, you know. You don't have to hold the book."<</speech>>
<<speech "Karlee">>"I'm reading it."<</speech>>
<<speech "$name">>"It's upside down."<</speech>>
<<speech "Karlee">>"…It's a //challenging// book."<</speech>>
Myra is already on the sofa, upside down herself, feet up the back cushions, one earbud in and one out — the universal signal that she is available for commentary but not participation.
<<speech "Myra">>"This is going to be great. I've brought no snacks and no goodwill."<</speech>>
<<speech "Avi">>"Why are you even here?"<</speech>>
<<speech "Myra">>"Marie and Blake are being disgusting in our room. Again. I'd rather watch you fail statistics."<</speech>>
<<speech "Avi">>"I'm not going to //fail//—"<</speech>>
<<speech "Myra">>"Sorry. Watch you succeed at statistics, loudly, while insisting you didn't need help."<</speech>>
<<speech "$name">>"Myra, if you're staying you're doing question fourteen."<</speech>>
<<speech "Myra">>"I'm an observer by nature."<</speech>>
<<speech "$name">>"Question fourteen."<</speech>>
<<speech "Myra">>"…Fine, but under protest and without sitting up."<</speech>>
Avi opens the textbook with unnecessary force.
She's difficult for the first twenty minutes in a way that's obviously armour — talking over your explanations, answering before you finish the question, treating every correction as an accusation. You stop correcting her. You start asking what she thinks the answer //means// instead, which annoys her enormously and works immediately.
Then she gets one right. Properly right, working it through out loud, and for about a second and a half her whole face changes.
<<speech "Avi">>"…that's it? That's all it was?"<</speech>>
<<speech "$name">>"That's all it was."<</speech>>
<<speech "Avi">>"Well. Obviously. I //said// I didn't need this."<</speech>>
<<speech "$name">>"You did say that."<</speech>>
<<speech "Avi">>"Don't say it like that."<</speech>>
<<speech "$name">>"Like what?"<</speech>>
<<speech "Avi">>"Like you're //pleased//."<</speech>>
She says it too fast. Across the room, Karlee looks up from her upside-down book and catches your eye, and neither of you says anything.
<<speech "Myra">>"That was nice. Don't ruin it."<</speech>>
<<speech "Avi">>"Shut up, Myra. What did you get for fourteen?"<</speech>>
<<speech "Myra">>"A profound sense of my own limitations."<</speech>>
<<elseif _tier is 2>>
Avi has started arriving early.
She has never once acknowledged it. She turns up twenty minutes before the session, says something dismissive about having nothing better to do, and installs herself at the table — and lately she has stopped sitting across from you and started sitting beside you, close, her thigh warm against yours the whole way through.
<<speech "Avi">>"Explain the last bit again. Not because I didn't get it. Because you explain it in a stupid way and I want to hear it again."<</speech>>
<<speech "$name">>"You want to hear the stupid way again."<</speech>>
<<speech "Avi">>"Yes."<</speech>>
<<speech "$name">>"Move closer, then. You can't hear it from all the way over there."<</speech>>
She's already pressed against your shoulder. She moves closer anyway, and neither of you laughs, and that is the strange part.
She's wearing a top she definitely did not wear to class, she has arranged herself so that leaning over the textbook does something specific, and her hand has been resting on your knee for six minutes.
<<speech "Myra">>"Oh my //god//."<</speech>>
<<speech "Avi">>"What."<</speech>>
<<speech "Myra">>"Nothing. Nothing at all. Please continue explaining the stupid thing in the stupid way."<</speech>>
Myra is on the sofa with both earbuds out, which for Myra is roughly equivalent to standing on the table and shouting. She's watching with the delighted focus of a woman who has found something better than music — and one hand has been inside the waistband of her joggers for a while now, moving in a slow idle rhythm she does not appear to have noticed starting.
Karlee is not in the armchair. Karlee is behind your chair with her hands on your shoulders, ostensibly reading the page over your head, and she has been kneading the muscle at the base of your neck for several minutes with a slow thoroughness that has nothing whatsoever to do with statistics.
<<speech "Karlee">>"You're tense."<</speech>>
<<speech "$name">>"I'm tutoring."<</speech>>
<<speech "Karlee">>"You're //tense//."<</speech>>
<<speech "$name">>"Lower."<</speech>>
There is a pause of about one second in which the old version of you would have said something to take it back.
<<speech "Karlee">>"…Lower."<</speech>>
Her thumbs work down either side of your spine. She bends further over the back of the chair, her massive chest presses against the back of your head, she doesn't move away — and you tip your head back into her instead of forward.
Avi's hand has migrated well up your thigh. She has stopped looking at the textbook entirely.
<<speech "Avi">>"Am I interrupting the massage or is the massage interrupting me? Because I booked this slot."<</speech>>
<<speech "Karlee">>"There's no slot. There's a table and a textbook."<</speech>>
<<speech "Avi">>"There's a //record//—"<</speech>>
<<speech "$name">>"There's no record, Avi. There's never been a record."<</speech>> You put your hand over hers and move it another two inches up. <<speech "$name">>"Keep going. Nobody's writing any of this down."<</speech>>
<<speech "Avi">>"…Okay."<</speech>>
It comes out quiet and completely unarmoured, and she blinks like she's surprised at her own voice, and then she does keep going.
Karlee leans down past your ear and, instead of finishing the argument, kisses you — upside down, unhurried, one hand sliding down your chest. You catch the back of her neck to keep her there, which she was not expecting, and she makes a small approving noise into your mouth.
From the sofa, without any embarrassment whatsoever:
<<speech "Myra">>"Don't stop on my account."<</speech>>
<<speech "$name">>"You could come over here."<</speech>>
<<speech "Myra">>"…I'm building to it."<</speech>>
She does not come over. She does not take her hand out of her joggers either, and nobody in the room finds either fact worth mentioning.
<<elseif _tier is 3>>
Nobody brings the textbook any more.
Avi still calls it tutoring. She calls it that on the way in, every time — the last shred of the joke she's been hiding behind since the first session — and then she's on her knees before the door has finished closing, because you stopped waiting for her to make the first move somewhere around the third week and she has never once complained about it.
<<speech "Avi">>"Tutoring,"<</speech>> she says, working your belt open. <<speech "Avi">>"I'm being tutored. Right now. Educationally."<</speech>>
<<speech "$name">>"Then pay attention."<</speech>>
<<speech "Avi">>"Oh, I'm //so// good at this bit—"<</speech>>
<<speech "Myra">>"That's the only bit you're good at."<</speech>>
<<speech "Avi">>"That's what I //said//."<</speech>>
The armour came off in stages and this is what was under it. She's loud — she was always going to be loud — but the volume has changed character. It isn't performance any more. It's relief.
She works you with both hands and her whole face, sloppy and enthusiastic and entirely without technique, and every so often she surfaces to talk because she cannot help talking.
<<speech "Avi">>"I couldn't read the— I couldn't read the second chapter. The letters kept moving. I never told anyone that. I never told //anyone//."<</speech>>
<<speech "$name">>"I know. You read it out loud to me in week two and stopped halfway."<</speech>>
<<speech "Avi">>"You //knew//?"<</speech>>
<<speech "Karlee">>"Everyone knew."<</speech>>
<<speech "Avi">>"Everyone—"<</speech>>
<<speech "Karlee">>"Nobody minded. That's the bit you could never work out."<</speech>>
<<speech "$name">>"Look at me."<</speech>> You take her jaw and hold it until she does. <<speech "$name">>"You don't have to be the cleverest person in this room. Nobody in this room is keeping score."<</speech>>
<<speech "Avi">>"…You can't just //say// that while I'm—"<</speech>>
<<speech "$name">>"Say it back. Then get on with it."<</speech>>
<<speech "Avi">>"Nobody's keeping score. Nobody's keeping — okay — okay—"<</speech>>
She goes back down and doesn't come up for a while.
Karlee is beside you on the arm of the chair, top off, one hand in Avi's hair setting her pace — pragmatic and unhurried, running this the way she runs the dorm sheet. Supervision, in the end, was always what it was going to be.
<<speech "Karlee">>"Slower. He's close and you'll waste it."<</speech>>
<<speech "Avi">>"I don't //want// to be slower—"<</speech>>
<<speech "$name">>"Do what she says."<</speech>>
<<speech "Avi">>"…Fine. //Fine.//"<</speech>>
<<speech "Karlee">>"Thank you."<</speech>>
<<speech "$name">>"Don't thank me. You're the one who's right."<</speech>>
<<speech "Karlee">>"I know I'm right. I like being told."<</speech>>
Myra has finally left the sofa. She's kneeling beside the chair with one earbud still absurdly in, watching from about eight inches away, her hand down the front of her own jeans.
<<speech "Myra">>"I've spent two years listening to Marie and Blake through a wall. Two years. And it turns out I just wanted a better seat."<</speech>>
<<speech "Karlee">>"You could participate, you know."<</speech>>
<<speech "Myra">>"I'm building to it. I'm an observer by nature."<</speech>>
<<speech "Avi">>"She's been //observing// with her hand in her pants for twenty minutes—"<</speech>>
<<speech "Myra">>"Nature is complicated."<</speech>>
<<speech "$name">>"Then observe from here."<</speech>>
You pull her in by the wrist, and Karlee tips Avi's head aside to make room, and Myra — who has spent years being too cool to want anything out loud — takes her turn without a single word of protest.
When you finish it's over both their faces, and Karlee holds them there by the backs of their necks until they've dealt with it between them, because Karlee is not going to have the carpet ruined again.
<<speech "Myra">>"…Okay. I'm participating."<</speech>>
<<speech "Karlee">>"Noted."<</speech>>
<<speech "Avi">>"There's no //record//—"<</speech>>
<<else>>
The common room has stopped being a common room. The table is against the wall. The textbook is under the sofa where it fell a long time ago and nobody has thought about it since.
Avi is on her back on the floor with her legs over your shoulders, and every trace of the girl who needed to be the loudest person in the room has been rendered down into something simple and pleading.
<<speech "Avi">>"I'm not clever. I'm not — I don't have to be clever any more, do I. Tell me I don't have to be."<</speech>>
<<speech "$name">>"You don't."<</speech>>
<<speech "Avi">>"//Thank you.//"<</speech>> She sobs it. <<speech "Avi">>"Thank you, thank you, breed me, I don't have to be anything—"<</speech>>
<<speech "$name">>"You have to be one thing."<</speech>>
<<speech "Avi">>"Anything. Tell me. //Tell me the one thing.//"<</speech>>
<<speech "$name">>"Mine."<</speech>>
<<speech "Avi">>"Yours. Yours, yours, I can do that, that's //easy//—"<</speech>>
Karlee kneels over her head facing you, riding Avi's mouth, holding the girl's wrists to the carpet with a calm proprietary strength. The parasite has taken the part of her that organised the sheet and given it something better to organise.
<<speech "Karlee">>"She goes twice. She needs it twice or she gets loud again."<</speech>> Flushed, hair stuck to her neck, entirely composed. <<speech "Karlee">>"Then Myra. Myra's been waiting all evening and she'll never say."<</speech>>
<<speech "Myra">>"I would've said."<</speech>>
<<speech "Karlee">>"You never say."<</speech>>
<<speech "Myra">>"…I would've //eventually// said."<</speech>>
<<speech "$name">>"Myra. Down here. You've observed for years, that's long enough."<</speech>>
<<speech "Myra">>"…Oh, thank //fuck//."<</speech>>
Myra comes off the sofa so fast she takes a cushion with her — naked, both earbuds finally gone, the parasite's veining laced up the insides of her thighs — and folds down onto the carpet beside Avi with an obedience that would be embarrassing in a woman who spent years being too cool to want things, if there were anyone left in her to be embarrassed.
<<speech "Myra">>"For the record — since Avi's so big on the record — this is the best thing that's ever happened in this building."<</speech>>
<<speech "Avi">>"There's no record. There's a //table// and a—"<</speech>>
She loses the rest of it as you drive into her, and Karlee's hand comes down over her mouth, and Myra presses her forehead to Avi's temple and watches from four inches away with her mouth open and her hand working between her own legs in time with you.
You breed Avi twice, as instructed. The second time she doesn't form words at all, just a long ruined sound into Karlee's palm, and afterwards Karlee tilts her hips up onto a cushion and holds them there without being asked.
Then Myra, on her hands and knees on the carpet, sarcasm entirely gone, saying //please// over and over in a voice she would have died before using a year ago.
<</if>>
<<case "Dorm_Hall_Standard">>
<<if _tier is 0 or _tier is 1>>
You open the door to find Emily, Kylie, and Laila standing in the hallway. The dorm corridor is quiet, afternoon light filtering through the windows at the end, the smell of someone's microwave popcorn lingering in the air. It's an ordinary Wednesday, the kind of ordinary that will soon become impossible to remember.
Emily is fidgeting nervously, her dark hair falling forward to hide her face, her small hands clutching the strap of her bag. She wears an oversized sweater that swallows her petite frame, her solid ass hidden beneath layers of fabric, her dark eyes cautious but warm. She's been your family for years now, ever since she escaped the abuse that marked her early life, and she still fidgets when she surprises you, still expects to be turned away.
<<speech "Emily">>"…I hope we're not bothering you."<</speech>>
Kylie is bouncing on her toes beside her, the youngest cousin, her dark brown hair in a ponytail that swings with every movement, her wide smile infectious. She wears jeans and a bright t-shirt, her petite body vibrating with energy, her playful nature making her incapable of standing still. She holds up a bag of snacks like a trophy.
<<speech "Kylie">>"Yeah! We brought snacks! Of course we're not bothering him, Emily. He loves when we visit, right $name?"<</speech>> She grins, nudging Emily playfully, her energy filling the narrow hallway.
Laila stands slightly apart, her long wavy blonde hair catching the light, her blue eyes soft with that permanent gentle expression, her light freckles visible even in the dim corridor. She wears a soft cardigan over a summer dress, her petite toned body relaxed, her nature always putting others first. She's been your neighbor since before your parents died, has helped your family through everything, and her kindness is as constant as the seasons.
<<speech "Laila">>"Hi $name! We were in the area and thought we'd surprise you,"<</speech>> she says gently, her kind nature shining through. <<speech "Laila">>"We can leave if you're busy. We didn't mean to impose."<</speech>>
<<speech "Kylie">>"Speak for yourself! I meant to impose. I brought the good chips!"<</speech>>
You step back, inviting them in. The dorm room is small, a desk, a bed, a chair, but they fill it with warmth—Emily finding the corner of your bed to perch on, Kylie immediately claiming the floor to spread out her snacks, Laila settling into your desk chair with the grace of someone who has made herself at home in a hundred similar spaces.
They talk about nothing: Kylie's adventures, Laila's neighborly observations, Emily's quiet contributions about her day. The afternoon stretches, comfortable, safe, familial. Emily's fidgeting slows. Kylie's bouncing finds a rhythm. Laila's smile remains constant. It is ordinary. It is precious. It is the last time anything will be this simple.
<<elseif _tier is 2>>
The hallway is empty when you open the door, but the air is wrong—thick, warm, sweet like fruit left too long in the sun. They are waiting inside. They have let themselves in. They should not have let themselves in.
Emily stands by your bed, her oversized sweater gone, her tank top thin and clinging to her petite frame, her solid ass visible in leggings that have become somehow too tight, too revealing. She is flushed, her dark eyes wide and wet, her thighs pressed together, her hands clutching the bedpost like she might float away.
<<speech "Emily">>"…I shouldn't have come. I felt it downstairs. I felt it in the elevator,"<</speech>> she whispers, her voice shaking. <<speech "Emily">>"My body gets so hot when I think about you. When I'm near you. It's wrong. I'm your— you're my—"<</speech>> She gasps, her hips bucking slightly against nothing, her face contorting with pleasure she cannot control.
Kylie is on your floor, her jeans unbuttoned, her hand inside her panties, her petite body writhing. The playful energy has become something desperate, her wide smile replaced by an open mouth, her ponytail fallen out, her dark hair wild.
<<speech "Kylie">>"I feel all tingly and weird… like I need something but I don't know what,"<</speech>> she says, her voice high and breaking. <<speech "Kylie">>"I was touching myself in the hallway. I couldn't stop. I could smell you from the elevator."<</speech>> Her hand moves faster, her hips lifting, her face transforming into something slack and desperate—ahegao in the making, tongue out, eyes rolling.
Laila is in your desk chair, but she has turned it to face you, her summer dress hiked up, her gentle nature completely shattered by need. Her toned legs are spread, her hand between them, her blue eyes glazed, her freckled face flushed deep red.
<<speech "Laila">>"$name… I feel so strange today. My body keeps getting really hot whenever I think about coming to see you,"<</speech>> she admits softly, her breathing heavy, her hips rocking against her hand. <<speech "Laila">>"We probably shouldn't have come… but I didn't want to cancel. I couldn't cancel. I need—"<</speech>>
She comes with a gasp, her body convulsing, her face frozen in ahegao—mouth open, tongue lolling, eyes rolled back, drool on her chin, her gentle kindness transformed to pure physical need.
They converge on you, Emily's hand finding your thigh, Kylie's hand joining hers, both stroking you through your jeans, Laila watching with glazed eyes, her hand still moving between her legs.
<<speech "Emily">>"…Please. Please let me help. Let me be useful,"<</speech>> she whispers, her trauma finding new expression in desperate service.
<<speech "Kylie">>"I want to make you feel good! I want to be good for you!"<</speech>> she babbles, her hand stroking you frantically, her ahegao face complete—tongue out, eyes crossed, drool spilling.
<<speech "Laila">>"Master—"<</speech>> The word escapes Laila, and her face flushes darker, but her hand doesn't stop. <<speech "Laila">>"I didn't mean— I can't— Master, please—"<</speech>>
The parasite thrums in your mind: Their resistance is delicious. They won't last much longer. And they don't. They stroke you together, Emily's shy touch, Kylie's frantic energy, Laila's gentle hand, all converging, all desperate, all transforming family and neighbor and cousin into something else entirely.
<<elseif _tier is 3>>
The dorm room has become a temple. The door is locked, the afternoon light golden and thick, the air so heavy with pheromones it leaves a film on the skin. They are waiting, positioned, transformed.
Emily kneels by the bed, her tank top gone, her leggings pushed down to her knees, her petite body naked and trembling, her solid ass presented, her dark hair falling forward. Her face is already ahegao—mouth open, tongue out, eyes rolled back, drool on her chin, her quiet reserved nature completely destroyed.
<<speech "Emily">>"…Please let me taste you. I want to be useful. I want to serve. Master, please—"<</speech>>
Kylie is beside her, completely naked, her petite body flushed, her dark hair wild, her face contorted in exaggerated pleasure—tongue lolling, eyes crossed, drool spilling onto her small tits. She bounces on her heels, unable to stop moving, her energy turned to desperate sexual need.
<<speech "Kylie">>"We couldn't wait anymore… we need your cock so bad! Please, Master! Let me suck you! Let me be good!"<</speech>>
Laila is between your legs, her summer dress gone, her toned body marked with dark veining, her blonde hair tangled, her freckled face pressed to your thigh. She looks up at you with those blue eyes, completely devoted, completely lost, her gentle nature rewritten as pure worship.
<<speech "Laila">>"I've been trying to be good… but all I can think about is sucking you dry, Master. Please let me serve. Please let me taste."<</speech>>
They descend on you together, three mouths, three sets of hands, familial bonds dissolved into pure sexual devotion. Emily takes you first, her shy nature making her thorough, her tongue tentative then desperate, her face transforming further into ahegao as she takes you deeper, gagging slightly, drool spilling onto her small tits.
Kylie is loud and messy, her mouth replacing Emily's, her energy making her sloppy and eager, her tongue everywhere, her hands stroking what she can't take, her face frozen in ahegao—tongue out, eyes rolled back, moaning around you like a cock-hungry pet.
Laila is gentle but greedy, her mouth hot and wet, her tongue skilled, her hands cupping your balls, her face pressed to you, her ahegao expression complete—mouth stretched, eyes watering and rolling back, drool on her chin, her kindness turned to desperate need to please.
They share you, passing your cock between them, their faces pressed together, tongues sliding over each other, over you, drool mixing, ahegao expressions constant—mouths open, tongues out, eyes rolled back, utterly devoted. Emily's trauma finds healing in service. Kylie's playfulness finds focus in worship. Laila's kindness finds expression in submission.
<<speech "Emily">>(muffled, gagging, her face glazed) "Master… thank you… for letting me serve…"<</speech>>
<<speech "Kylie">>(pulling back, gasping, her face ahegao—tongue lolling, eyes crossed) "Master! Master! Please come! Let us taste! We need it!"<</speech>>
<<speech "Laila">>(gentle even in desperation, her face slack with ahegao pleasure) "Master… feed us… we've been so good…"<</speech>>
You come, spilling over their faces, their open mouths, their waiting tongues. They fight to catch it, to share it, their ahegao expressions complete—eyes rolled back, tongues out, mouths open, drool and cum mixing, utterly possessed, utterly devoted.
<<else>>
The dorm room is a breeding nest. The bed is stained, the air thick, the afternoon light turned golden and obscene. They greet you on all fours, naked, bodies marked with dark veining, pussies swollen and leaking, bellies softly rounded from previous breedings, their faces still slack with ahegao devotion.
Emily is first, her petite body presented, her solid ass in the air, her dark hair tangled, her face turned back toward you in complete ahegao—mouth open, tongue out, eyes rolled back, drool on her chin, her quiet gratitude transformed to desperate begging.
<<speech "Emily">>"I feel safe when you're inside me… please fill me until I overflow, Master. Please breed me. Please make me yours completely."<</speech>>
You take her, filling her, breeding her, and she comes immediately, her body convulsing, her face frozen in ahegao—tongue lolling, eyes rolling back completely, drool spilling, her trauma healed in total possession. <<speech "Emily">>"Master… Master… thank you… for making me safe…"<</speech>>
Kylie is next, her playful nature reduced to pure breeding stock, her petite body shaking with need, her face ahegao—mouth open, tongue out, eyes crossed, drool on her chin, her dark hair wild.
<<speech "Kylie">>"We've been waiting like good girls! Our cunts are so empty without your cum! Please breed us again! Knock me up, Master! Make me your little breeding slut!"<</speech>> She shakes her ass, her energy turned to desperate sexual display, and you take her, pounding her, filling her womb, marking her as yours. She comes screaming, her face frozen in ahegao, her playfulness complete in total submission.
Laila last, her gentle nature transformed to pure breeding devotion, her toned body presented, her blonde hair tangled, her freckled face ahegao—slack, mouth open, tongue out, eyes rolled back, drool pooling on the floor.
<<speech "Laila">>"Please… fill me. I want to carry your child, Master. I want to be heavy with your seed. Please breed your gentle little slut. Please make me useful."<</speech>>
You breed her, completing the set, filling her womb, claiming her completely. She comes silently, her body shaking, her face frozen in ahegao devotion, her kindness satisfied in total possession.
Afterwards, the three of them lie together on your dorm floor, cum dripping from them, bellies softly rounded, faces still slack with ahegao pleasure—mouths open, tongues out, eyes rolled back, utterly devoted, utterly bred. Family, neighbor, cousin, all reduced to the same thing: warm, willing, breeding flesh, grateful for connection at last.
<<speech "Emily">>(whispering, her trauma completely healed) "Master… thank you… for filling me…"<</speech>>
<<speech "Kylie">>(giggling, her playfulness satisfied) "Master… I'm going to be such a good mommy for you…"<</speech>>
<<speech "Laila">>(gentle, even in total submission) "Master… I exist to serve you… forever…"<</speech>>
<</if>>
<<case "Sorority_Standard">>
<<if _tier is 0 or _tier is 1>>
The sorority house is everything the university brochures promise—white columns, polished floors, the smell of vanilla candles and fresh flowers and the particular tension of a dozen women living in forced harmony. Nancy leads the tour with practiced efficiency, her light brown hair swept back in a perfect ponytail, her blue eyes scanning for imperfections, her toned body moving through the space like she owns it, which in every way that matters, she does.
<<speech "Nancy">>"This is the main hall. We hold meetings here, host events, and occasionally have formal dinners."<</speech>> Her voice is smooth, polished, the voice of someone who has been managing appearances since she could walk. <<speech "Nancy">>"The bedrooms are upstairs. Each room can fit two to three girls comfortably."<</speech>>
Yulia follows behind her, her straight ash-blonde hair catching the light, her blue-gray eyes wide with quiet curiosity, her soft neutral expression taking in everything. She wears a modest dress that hides her big boobs and ass, her petite frame otherwise lost in the fabric, her Eastern European reserve making her slightly apart from the American exuberance around her.
<<speech "Yulia">>"It is very… grand,"<</speech>> she says politely, her voice soft, her accent gentle. <<speech "Yulia">>"In my country, we do not have such houses."<</speech>>
Avi trails behind them both, her medium-length wavy brown hair with lighter ends falling in her face, her blue eyes bright with barely suppressed judgment, her fair-to-medium skin flushed slightly with the effort of keeping her mouth shut. She wears jeans and a t-shirt, her bushy pussy hidden beneath, her loud, opinionated nature contained only by her desire to prove she doesn't need to be here.
<<speech "Avi">>"What she means is we have a lot of rules and a lot of expectations. But the WiFi is good,"<</speech>> Avi says dryly. <<speech "Avi">>"I've seen five rooms and heard about seventeen rules."<</speech>>
She spots you passing through the hall, her tutor, her supposed academic salvation, and her expression sharpens with the defensive brashness that hides her insecurity.
<<speech "Avi">>"Oh great. The token guy is here."<</speech>>
<<speech "Nancy">>"$name is always welcome. He helps with events."<</speech>> Nancy's smile is professional, perfect, revealing nothing of the exhaustion beneath. <<speech "Nancy">>"And Avi, you've been assigned tutoring for a reason. Academic probation is not a rumor."<</speech>>
<<speech "Avi">>"I'm not on probation. I'm on //academic observation//. There's a difference."<</speech>>
<<speech "Yulia">>"You are $name, yes? I have seen you around. I am Yulia. I am learning your ways."<</speech>> She says it softly, her curiosity genuine, her shyness evident.
You stand in the main hall, the four of you, and the afternoon stretches—Nancy managing, Yulia observing, Avi resisting, you passing through. It is ordinary. It is tense. It is the beginning of something that will transform all of them.
<<elseif _tier is 2>>
The common area is empty when you find them, the afternoon light filtering through the tall windows, the vanilla candles burning down, the air somehow thicker, warmer, wrong.
Nancy stands by the fireplace, her polished ponytail fallen out, her light brown hair wild, her blouse unbuttoned to show her toned stomach, her skirt hiked up. She is flushed, her blue eyes glazed, her perfect poise cracking, her exhaustion finally finding expression in physical need.
<<speech "Nancy">>"I can't—I can't maintain it today. The house, the drama, the alumnae,"<</speech>> she gasps, her hand between her legs, pressing through her skirt. <<speech "Nancy">>"I feel so hot when you're near. I can't think. I can't manage. I just want—"<</speech>>
Avi is on the couch, her jeans unbuttoned, her hand inside her panties, her bushy pussy visible, her loud nature silenced into desperate panting. Her brash confidence has been reduced to begging, her insecurity exposed as pure sexual need.
<<speech "Avi">>"Oh great. The tutor is here. Just what I needed,"<</speech>> she manages, her voice breaking, her hips bucking. <<speech "Avi">>"Why the hell do I get so wet every time you show up lately? I thought you were boring. I thought you were quiet. And now I can't stop touching myself thinking about you. I want to drag you upstairs. I want to—"<</speech>> She comes with a gasp, her face transforming into ahegao—mouth open, tongue out, eyes rolling back, drool on her chin, her opinionated nature completely shattered.
Yulia is by the window, her modest dress hiked up, her big boobs exposed, her hand between her legs, her soft-spoken nature reduced to whimpering need. Her Eastern European reserve has cracked completely, her curiosity turned to desperate sexual exploration.
<<speech "Yulia">>"I feel it too… it's like a fever that only gets worse when $name is near,"<</speech>> she says softly, her accent thickening with arousal, her hips rocking against her hand. <<speech "Yulia">>"In my country, we do not speak of such things. But I cannot stop. I want to learn. I want to know. Master—"<</speech>> The word escapes her, and her face flushes, her hand moves faster, her ahegao expression forming—mouth open, tongue lolling, eyes rolled back, drool spilling onto her big tits.
They converge on you, Nancy's hand stroking you through your pants, her management skills turned to sexual service, Avi's hand joining hers, both stroking you frantically, Yulia watching with glazed eyes, her hand still moving between her legs, her curiosity satisfied in observation.
<<speech "Nancy">>(her voice breaking, her poise gone) "We're not supposed to feel like this. But I want to serve you. I want to stop managing and be managed. Master, please—"<</speech>>
<<speech "Avi">>(her brashness completely gone, her face ahegao—tongue out, eyes crossed) "I used to think I was better than everyone. Now I just want to be your slut. Master, please, let me serve you. Let me make up for being such a bitch."<</speech>>
<<speech "Yulia">>(softly, her accent thick, her face slack with ahegao pleasure) "I am learning your ways, Master. Please teach me. Please let me serve."<</speech>>
The three of them stroke you together, the sorority president, the loud insecure girl, the curious foreign exchange student, all reduced to the same desperate need, all transforming into worshippers, all begging for the same thing: your cock, your cum, your possession.
<<elseif _tier is 3>>
The sorority house main hall has become a temple of corruption. The white columns stand witness, the polished floors reflect the obscene scene, the vanilla candles burn mixed with the thick musk of pheromones. They are waiting, positioned, transformed—dressed like sorority sluts, micro skirts, tiny tops, no underwear, their pussies visibly dripping.
Nancy kneels in the center, her polished poise completely shattered, her light brown hair wild, her toned body flushed, her face already ahegao—mouth open, tongue out, eyes rolled back, drool on her chin, her exhaustion finally finding relief in total submission.
<<speech "Nancy">>"Thank God you're here… I've been aching to serve you all day, Master. I can't manage anymore. I can't lead. I just want to follow. I just want to suck. Please let me serve."<</speech>>
She takes you into her mouth with the efficiency she brings to everything, her tongue skilled, her throat working, her face transforming further into ahegao as she takes you deeper, gagging slightly, drool spilling onto her toned stomach, her leadership completely rewritten as devoted cocksucking.
Avi is beside her, completely naked, her bushy pussy visible, her loud nature silenced into desperate worship, her face contorted in exaggerated ahegao—tongue lolling, eyes crossed, drool spilling onto her small tits.
<<speech "Avi">>"I used to think you were boring… now I just want your cock down my throat, Master. I want to gag on it. I want to be messy. I want to be your loud little slut."<</speech>>
She takes you from Nancy, her mouth replacing the president's, her brash nature making her sloppy and eager, her tongue everywhere, her hands stroking what she can't take, her face frozen in ahegao—tongue out, eyes rolled back, moaning like a cock-hungry whore.
Yulia is between your legs, her big boobs pressed against your thighs, her ash-blonde hair falling forward, her soft-spoken nature transformed to curious, eager worship. Her face is ahegao—mouth stretched, eyes watering and rolling back, drool on her chin, her Eastern European reserve completely destroyed.
<<speech "Yulia">>"I have never felt this way before… please let me taste you, Master. I want to learn. I want to know everything. Please teach me how to serve."<</speech>>
They share you, the three of them, passing your cock between their mouths, their faces pressed together, tongues sliding over each other, over you, drool mixing, ahegao expressions constant—mouths open, tongues out, eyes rolled back, utterly devoted. Nancy's efficiency makes her thorough. Avi's brashness makes her messy. Yulia's curiosity makes her eager to learn.
<<speech "Nancy">>(pulling back, elegant even while gagging, her face glazed) "We are yours. Use our mouths however you want, Master. We exist to serve you."<</speech>>
<<speech "Avi">>(loud even with her mouth full, her face ahegao—tongue lolling, eyes crossed) "Master! Please come! Let us taste! We need it! We've been so good!"<</speech>>
<<speech "Yulia">>(softly, gently, her face slack with ahegao pleasure) "Master… please feed us… we are hungry for you…"<</speech>>
You come, spilling over their faces, their open mouths, their waiting tongues. They fight to catch it, to share it, their ahegao expressions complete—eyes rolled back, tongues out, mouths open, drool and cum mixing, utterly possessed, utterly devoted. The sorority president, the loud insecure girl, the curious foreign exchange student, all reduced to the same thing: cock-hungry, cum-drunk, worshipping whores.
<<else>>
The sorority house has become a luxurious breeding nest. The white columns stand, the polished floors are stained, the vanilla candles burn out, replaced by the thick musk of sex and pheromones. They greet you on all fours in the main hall, naked, bodies marked with dark veining, pussies swollen and constantly leaking, bellies softly rounded from previous breedings, their faces still slack with ahegao devotion.
Nancy is first, her leadership completely rewritten into devoted submission, her light brown hair wild, her toned body presented, her face turned back toward you in complete ahegao—mouth open, tongue out, eyes rolled back, drool on her chin, her exhaustion finally satisfied in total possession.
<<speech "Nancy">>"Welcome back, Master… we've been keeping our wombs warm for you. Please breed us. Please fill us. We exist to carry your seed."<</speech>>
You take her, filling her, breeding her in the main hall she once managed, and she comes immediately, her body convulsing, her face frozen in ahegao—tongue lolling, eyes rolling back completely, drool spilling, her leadership destroyed in total submission. <<speech "Nancy">>"Master… thank you… for breeding your slut…"<</speech>>
Avi is next, her brashness completely transformed to pure breeding devotion, her bushy pussy presented, her face ahegao—mouth open, tongue out, eyes crossed, drool on her chin, her insecurity healed in total possession.
<<speech "Avi">>"Hey Master... why don't you fuck me stupid and knock me up? I want to be your loud little breeding slut. I want to be full of your cum. Please, Master, breed me until I can't think anymore."<</speech>>
You take her, pounding her, filling her womb, marking her as yours. She comes screaming, her face frozen in ahegao, her brashness complete in total submission, her insecurity destroyed in pure devotion.
Yulia last, her curiosity completely satisfied, her Eastern European reserve completely destroyed, her big boobs and ass presented, her face ahegao—slack, mouth open, tongue out, eyes rolled back, drool pooling on the polished floor.
<<speech "Yulia">>"Please… fill me. I want to carry your child, Master. I want to learn everything. I want to know what it means to be bred. Please teach me, Master. Please make me your pregnant little slut."<</speech>>
You breed her, completing the set, filling her womb, claiming her completely. She comes silently, her body shaking, her face frozen in ahegao devotion, her curiosity satisfied in total possession.
Afterwards, the three of them lie together on the sorority house floor, cum dripping from them, bellies softly rounded, faces still slack with ahegao pleasure—mouths open, tongues out, eyes rolled back, utterly devoted, utterly bred. The sorority president, the loud insecure girl, the curious foreign exchange student, all reduced to the same thing: warm, willing, breeding flesh, grateful for possession at last.
<<speech "Nancy">>(whispering, her leadership completely gone) "Master… thank you for breeding your sorority sluts…"<</speech>>
<<speech "Avi">>(giggling, her brashness satisfied) "Master… I'm going to be such a good breeding whore for you…"<</speech>>
<<speech "Yulia">>(softly, even in total submission) "Master… I have learned… I exist to serve you… forever…"<</speech>>
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<set $sceneColor = "#44ff88">>
<<set $sceneLabel = "Residential · Homes">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "House_Family">>
<<if _tier is 0 or _tier is 1>>
The living room is warmly lit, a sanctuary of worn comfort against the evening outside. Jewelz sits cross-legged on the couch, folding laundry with methodical precision, her blue hair falling in vibrant curtains around her face. She wears an oversized band tee and leggings, her curvaceous figure relaxed but alert, always the guardian of this space. Elsa has claimed the entire armchair, her body sprawled in impossible angles as she scrolls her phone, wearing tiny sleep shorts and a cropped tank that shows her midriff. Emily curls in the corner armchair, knees drawn up, a book held close like a shield, dressed in an oversized sweater that swallows her small frame.
Elsa glances up as $name enters, her energy crackling even in stillness.
<<speech "Elsa">>"Well well, look who finally decided to grace us with his presence."<</speech>>
Jewelz looks over with a tired but fond smile, her striking features softening.
<<speech "Jewelz">>"Dinner's in the oven. You're later than usual."<</speech>>
<<speech "Elsa">>"Yeah, what were you doing? A date with Aria? Or just brooding in the woods again?"<</speech>> Elsa teases, raising an eyebrow, her lively personality filling the room.
Emily looks up quietly from her book, her dark eyes cautious but warm.
<<speech "Emily">>"…Welcome home."<</speech>>
Jewelz folds a shirt neatly, her movements practiced from years of keeping this family together.
<<speech "Jewelz">>"Ignore your $family. She's been restless all evening."<</speech>>
<<speech "Elsa">>"Restless? I'm bored. There's a difference,"<</speech>> Elsa says, stretching dramatically, her tank riding up further. <<speech "Elsa">>"Emily won't let me put on music because she's reading, and Jewelz keeps telling me to 'act like a lady'."<</speech>>
<<speech "Jewelz">>"Someone has to maintain some standards in this house,"<</speech>> Jewelz replies with a sigh, though there's clear affection in her voice. <<speech "Jewelz">>"Especially when certain $family leave clothes everywhere."<</speech>>
<<speech "Elsa">>"That's called 'decorating', Jewelz. Very avant-garde."<</speech>>
Emily smiles softly, a rare expression that transforms her guarded face.
<<speech "Emily">>"It's peaceful like this."<</speech>>
Elsa groans but there's no real malice in it.
<<speech "Elsa">>"Peaceful is code for boring. Come on, $name, back me up here. We should do something. Movie? Game? Anything?"<</speech>> She looks at him with that infectious energy, always seeking connection, always in motion.
Jewelz shakes her head, but she's smiling.
<<speech "Jewelz">>"Let him breathe first, Elsa. He just walked in."<</speech>> She pats the couch beside her. <<speech "Jewelz">>"Sit. Eat. Then we can discuss entertainment options."<</speech>>
<<speech "Emily">>(quietly) "…There's leftover cake too. I saved you a piece."<</speech>> She looks down quickly, as if embarrassed by the confession of this small kindness.
The room breathes with safety, with the complicated love of a family forged through loss and choice. Jewelz protective and weary, Elsa bright and chaotic, Emily quiet and grateful, all orbiting the warm center of this shared space.
<<elseif _tier is 2>>
The living room feels different, heavier, the air thick with something musky and sweet that seems to emanate from $name where he sits. The parasite has awakened, its pheromones permeating the safe space, beginning the slow erosion of sanctuary into something lewd.
Jewelz still sits on the couch, but her oversized band tee has become just a tee—she's removed her bra beneath it, the fabric thin enough to show the dark circles of her nipples when she moves. Her leggings are the same, but she's rolled them down lower, her hip visible when she shifts. She keeps "accidentally" brushing against $name as she folds, her blue hair falling forward to hide her flushed face.
<<speech "Jewelz">>(breathless, fanning herself) "Is it... is it hot in here? The oven's off, right?"<</speech>> She tugs at her tee, the motion making her breasts strain against the fabric. <<speech "Jewelz">>"I feel... dizzy."<</speech>>
Elsa has abandoned her armchair, moving to the floor near $name's feet, her sleep shorts hiked up impossibly high, her tank top twisted to expose more skin. She keeps touching her own thigh, her fingers tracing patterns, unable to sit still.
<<speech "Elsa">>(her usual energy turned breathless) "$name... when did you start smelling like that?"<</speech>> She looks up at him, her eyes glassy, her teasing nature transformed to something desperate. <<speech "Elsa">>"Like... like I want to..."<</speech>> She doesn't finish, her hand sliding up her own thigh under her shorts.
Emily has curled tighter in her corner, her oversized sweater somehow more revealing—she's pulled it down to expose one shoulder, her small hand clutching the collar. But she's watching, her dark eyes fixed on $name with an intensity that belies her quiet nature.
<<speech "Emily">>(whispering, almost to herself) "...You smell safe. But... but not safe. I want..."<</speech>> She shifts, her sweater riding up, her other hand disappearing beneath the fabric.
<<speech "Jewelz">>(noticing, her maternal concern warring with arousal) "Emily? Are you... are you touching yourself?"<</speech>> She should stop it. Should protect her. But Jewelz's own hand has found its way between her legs, pressing against her leggings.
<<speech "Emily">>(not stopping, her voice breathy) "...It feels good. I've never... but this feels good. He feels good."<</speech>> Her hand moves under her sweater, her hips rocking slightly, her trauma-damaged psyche finding something in $name's presence that overrides fear with desperate need.
<<speech "Elsa">>(groaning, her fingers sliding into her shorts) "Fuck, this is weird. I am your $family. This is wrong. But I can't..."<</speech>> She's fingering herself openly now, her energetic personality reduced to desperate motion, her eyes locked on $name. <<speech "Elsa">>"I can't stop. I need... I need to touch. To be touched."<</speech>>
Jewelz tries to stand, to maintain some semblance of her protective role, but she stumbles, falling to her knees in front of the couch, her face level with $name's lap. Her tee falls forward, her breasts visible, her blue hair tangled.
<<speech "Jewelz">>(whimpering, her hand still between her legs) "I should protect them. But I can't... I can't stop wanting..."<</speech>> She rocks back on her heels, her leggings soaked through where she's touched herself, her alternative beauty transformed to desperate need.
<<speech "Elsa">>(faster, harder, her hips bucking) "Jewelz... look at us. Look at what he's doing to us. And he hasn't even touched us. He just... exists. Smells. Is."<</speech>> She comes with a cry, her body convulsing, her shorts soaked, her hand still moving.
<<speech "Emily">>(quietly coming, her face flushed, her sweater hiding her expressions but not her rocking hips) "...Thank you. Thank you for making me feel this. Safe enough to be... to be bad."<</speech>> Her orgasm is silent, her trauma finding strange healing in this corruption.
Jewelz follows, her maternal authority shattered by her own climax, kneeling on the floor of her own living room, her family watching, participating, falling together into depravity.
<<speech "Jewelz">>(panting, her hand still on herself) "Again... I need to... the laundry can wait..."<</speech>>
<<speech "Emily">>(whispering, her dark eyes finally open and wanting) "...Will you touch me next? Please? I've never asked for that. But I want..."<</speech>>
The safe space breathes with new corruption, the family sanctuary becoming something else, the pheromones thickening, the fall beginning.
<<elseif _tier is 3>>
The living room has become unrecognizable as a sanctuary, transformed into a temple of slow corruption. Days have passed, or perhaps hours—time blurs when the parasite thickens the air. The furniture remains the same: the couch, the armchairs, the television playing some forgotten show. But the inhabitants have lost their minds to pheromones and need, their common sense eroded to naked instinct.
Jewelz attempts to fold laundry, her maternal routine preserved even in madness. She wears only an apron—one of her old band tees cut down the middle and tied behind her neck, the fabric barely covering her breasts, her curvaceous body naked beneath, blue hair tangled and wild. She keeps dropping the towels, her hands drifting between her legs instead, her blue eyes glazed and unfocused.
<<speech "Jewelz">>(mumbling to herself, folding and dropping) "Towels... fold the towels... keep the house... keep the family..."<</speech>> She bends over, her ass exposed, her fingers sliding into herself without thought. <<speech "Jewelz">>"Can't concentrate... need... need to taste him..."<</speech>>
Elsa sprawls across the armchair, her phone forgotten on the floor, her sleep shorts now just a torn strip of fabric that does nothing to cover her. Her tank top is soaked with her own saliva where she's been drooling, her nipples hard and visible, her energetic body constantly in motion even now—rocking, grinding, seeking.
<<speech "Elsa">>(whining, her hand between her legs) "Jewelz... stop folding laundry. Come here. Come suck him with me."<</speech>> She crawls to the floor, her $family instincts completely overwritten, her teasing nature become desperate begging. <<speech "Elsa">>"I need it. Need it in my mouth. Need to taste Master's... Master's..."<</speech>> She can't finish, her mind too far gone for complete sentences.
Emily sits in the corner, but she's abandoned her book. Her oversized sweater has become a belt around her waist, her small body naked, her trauma-damaged psyche completely rewired by the parasite. She rocks back and forth, her fingers inside herself, her dark eyes locked on $name with absolute devotion.
<<speech "Emily">>(whispering, rocking) "...Good girl... I'm a good girl... good girls serve... good girls suck..."<</speech>> She's repeating it like a mantra, her abuse history transformed into willing submission, her healing complete but corrupted. <<speech "Emily">>"Please... please let me be good... let me taste..."<</speech>>
$name sits on the couch, fully the host, his casual presence commanding without effort. The parasite has taken him completely, rare clarity moments flashing and dying in his eyes like dying stars.
Jewelz crawls to him first, her apron falling open, her maternal instinct transformed to desperate service. She pulls his cock free with hands that once cooked dinners, once bandaged wounds, now only capable of seeking pleasure.
She takes him deep, her blue hair falling forward, her curvaceous body naked and kneeling on her own living room floor, the laundry forgotten.
Elsa fights her way in, her energy chaotic, desperate. <<speech "Elsa">>"Share! Share! I need it!"<</speech>> She licks the base, her tongue hot and desperate, her $family connection to $name completely perverted into sexual competition. <<speech "Elsa">>"Suck him harder, Jewelz! Make him come! I want it too!"<</speech>>
Emily crawls last, her quiet nature making her slower, but her need just as desperate. She doesn't fight for space—she waits, her mouth open, her small hands stroking his thighs, her dark eyes pleading.
<<speech "Emily">>"...Please... I've been good... I've been waiting..."<</speech>>
They work him together, three women who were once loved ones, $family, rescued stray—all minds lost, all common sense gone, all that remains the need to serve, to suck, to taste. Jewelz bobs her head, her apron soaked with spit, her maternal authority reduced to skilled cocksucking. Elsa licks and strokes, her energy never flagging, her teasing nature become desperate worship. Emily takes him when they offer, her small mouth stretching, her trauma finding healing in being used, finally used, safely used.
<<speech "Jewelz">>(pulling back, gasping, her face glazed) "More... need more... can't think... only suck... only serve..."<</speech>>
<<speech "Elsa">>(faster, her hand between her own legs) "Make him come! Want to taste! Want to swallow!"<</speech>>
<<speech "Emily">>(muffled, her eyes rolling back) "Mmm... mmm..."<</speech>>
He comes with a groan, filling Jewelz's mouth first—she swallows desperately, maternal care become cum-hunger—then Elsa takes the next spurt, laughing and swallowing, her energy satisfied momentarily—then Emily catches the last, her quiet nature finally given voice through moaning submission.
They collapse together, a tangle of familial corruption, the living room smelling of sex and madness, the television still playing, the laundry scattered, daily life completely possessed.
<<else>>
The house breathes with the parasite, every room infected, every surface marked with cum and arousal. The kitchen, the bathroom, the hallway—nowhere is safe from the depravity that has consumed this family. The women have lost their minds completely, their common sense not just eroded but annihilated, their daily routines transformed into rituals of sexual worship.
Jewelz stands at the stove, attempting to make breakfast. She wears an apron—just an apron, one of $name's old shirts cut down and tied behind her neck, the fabric translucent with old stains, her curvaceous body completely naked beneath, her blue hair matted and wild. She holds a spatula in one hand, but her other hand is between her legs, constantly touching, constantly wet.
The eggs burn. She doesn't notice.
<<speech "Jewelz">>(mumbling, her eyes glazed) "Breakfast... make breakfast... for Master..."<</speech>> She bends over to check the oven, her ass exposed, her pussy dripping onto the floor tiles. <<speech "Jewelz">>"Master needs... needs protein... needs to breed..."<</speech>>
Elsa sits at the kitchen table, naked except for her sleep shorts cut into nothing, her tank top gone. She's eating cereal, but she's forgotten the spoon, drinking the milk directly from the bowl, letting it spill down her naked breasts, her energetic body rocking against the chair, her pussy leaving wet marks on the wood.
<<speech "Elsa">>(whining, her hand between her legs) "Jewelz... stop cooking. Come fuck me. Or let me watch. Or something. I'm bored."<</speech>> She stands, her body in constant motion even in madness, and crawls onto the table, knocking the cereal aside. <<speech "Elsa">>"Fuck me here. Breed me on the table. I'm your $family. It's wrong. Do it anyway."<</speech>>
Emily enters from the living room, crawling because walking has become too complicated with constant spikes of arousal, her oversized sweater now just a collar around her neck, her small body marked with handprints and cum, her dark eyes completely vacant except for devotion.
<<speech "Emily">>(whispering, crawling to $name's feet) "...Hungry... not for food... for Master..."<</speech>> She nuzzles his crotch through his pants, her trauma completely overwritten, her only language submission. <<speech "Emily">>"Please... breed me before breakfast... make me full..."<</speech>>
$name sits at the head of the table, fully the host, the parasite speaking through him in every casual gesture. He gestures lazily, commanding without effort, the pheromones so thick the air shimmers.
<<speech "$name">>"Jewelz. Bend over the stove. Elsa, underneath her. Emily, ride my face. Now."<</speech>>
They obey without thought, their minds completely gone, their common sense annihilated, daily life become sexual ritual.
Jewelz bends over the stove, her apron falling forward, her breasts hanging, her hands still trying to hold the spatula even as she presents herself. <<speech "Jewelz">>"Yes... yes... breed me while I cook... make me a mother again... your broodmare..."<</speech>>
Elsa slides underneath her, her mouth finding Jewelz's pussy, her energetic licking desperate and unskilled but eager, her own pussy exposed to the kitchen air, her $family nature completely perverted into incestuous service. <<speech "Elsa">>(muffled, licking) "Taste good... Jewelz tastes good... but need Master... need Master inside..."<</speech>>
Emily straddles $name's face in the kitchen chair, her small body bouncing, her trauma finding final healing in being completely used, her mind empty except for service. <<speech "Emily">>"...Thank you... thank you... good girl... breeding vessel..."<</speech>>
He takes Jewelz first, standing behind her at the stove, slamming into her with the spatula still in her hand, her maternal body milking him desperately, her blue hair falling into the eggs that burn forgotten.
<<speech "Jewelz">>(screaming, her mind completely gone) "Master! Master! Breed your $family! Fill my womb! Make me pregnant with your parasite spawn!"<</speech>> She comes hard, her walls convulsing, her kitchen become a breeding ground.
He fills her, flooding her womb, and she collapses onto the stove, the spatula falling, the eggs burning, her apron soaked with cum and sweat.
Elsa immediately takes her place, bending over the table, her energetic body presenting itself, her $family connection completely sexualized. <<speech "Elsa">>"Me! Me! Your $family! Breed me too! Make it wrong! Make it depraved!"<</speech>>
He takes her roughly, her body bouncing against the table, the cereal bowl falling, milk spilling, daily life completely destroyed by sexual madness.
<<speech "Elsa">>(laughing and screaming) "Yes! Yes! Fill me! Make me your $family whore! Your energetic little breeding slut!"<</speech>> She comes hard, her energy never flagging, her mind completely lost.
Emily last, pulled from his face and bent over the kitchen counter, her small body taking him deep, her quiet nature expressed in desperate moaning, her trauma completely healed through total corruption.
<<speech "Emily">>(whimpering, her mind empty) "...Master... Master... thank you for using me... thank you for making me safe... thank you for making me your whore..."<</speech>> She comes as he fills her, her body convulsing, her kitchen duty become breeding ritual.
They collapse together on the kitchen floor, the house burning around them metaphorically, the eggs smoking, the cereal spilled, three women completely mindless, their daily life fully possessed, their common sense gone, reduced to breeding vessels in their own home.
The parasite pulses in satisfaction. The home is claimed. The family is breeding stock.
<</if>>
<<case "House_Godmother">>
<<if _tier is 0 or _tier is 1>>
The living room hasn't changed much. Same lamp with the scorch mark on the shade, same sofa with the sunken end everyone fights over, same window that rattles when something heavy goes past on the main road.
Melissa is in the armchair we bought for her almost eleven years ago. Shoulder-length brown hair going lighter towards the ends, a cardigan older than some of the people in this room, and those green-hazel eyes that do a full inventory of you the second you come through the door and reach a conclusion she won't share.
She comes round two or three times a week. Nobody has ever formally agreed to this.
Melody and Elsa are on the floor between the sofa and the coffee table. Melody has Elsa sat between her knees and is working a braid into all that wavy platinum-blonde hair with the unhurried competence of someone who has done it several hundred times. Her own hair — long, golden, wavier than Elsa's — is shoved back off her face with a clip that is losing the argument.
<<speech "Elsa">>"Tighter."<</speech>>
<<speech "Melody">>"If I go tighter you'll complain in an hour."<</speech>>
<<speech "Elsa">>"I'll complain anyway. At least this way it'll look good while I do it."<</speech>>
The television is on and nobody is watching it. You take the sunken end of the sofa because you got here last, which is the rule.
<<speech "Melissa">>"You've lost weight."<</speech>>
<<speech "$name">>"I haven't."<</speech>>
<<speech "Melissa">>"Around the face. Your jaw's showing more than it did."<</speech>>
<<speech "$name">>"That's just what a jaw does, Melissa. It's structural. It's been there the whole time."<</speech>>
<<speech "Melissa">>"Not like that it hasn't."<</speech>>
<<speech "$name">>"You said the same thing at Christmas and I'd put on half a stone."<</speech>>
She makes a small noise that means she has decided to let you have that one and will be raising it again in about a week.
Melody, without looking up from the braid, quiet enough that it might not be meant for the room:
<<speech "Melody">>"He does look tired, though."<</speech>>
<<speech "Elsa">>"//Thank you.//"<</speech>>
<<speech "$name">>"Why are you thanking her?"<</speech>>
<<speech "Elsa">>"Because I said it on Tuesday and got told I was being dramatic."<</speech>>
<<speech "Melissa">>"You //were// being dramatic. You said he looked like a Victorian orphan."<</speech>>
<<speech "$name">>"I was standing in the rain waiting for a bus. That's not a personality, that's weather."<</speech>>
Melody's hands don't stop. She has a way of watching a conversation from underneath it, contributing one sentence every ten minutes and having it be the accurate one. She has been Elsa's best friend since they were nine and is here more evenings than she is at her own house.
The braid gets finished. Elsa reaches up, feels it, pronounces it acceptable, and immediately lies flat on the carpet, ruining it.
<<speech "Melody">>"…Right."<</speech>>
<<speech "Elsa">>"You can do it again. You like doing it."<</speech>>
<<speech "Melody">>"That is not the point I was making."<</speech>>
Melissa laughs into her tea. Outside a lorry goes past and the window rattles, and something turns over warm and slow in your chest, and you put it down to the room being over-heated.
<<elseif _tier is 2>>
The armchair has migrated. Not far — eighteen inches, maybe two feet — but it now sits close enough that when Melissa tucks her feet up her knees press against your thigh, and neither of you moves away from that for the whole evening.
She's in a summer dress that's wrong for the season, cardigan discarded over the arm. Bare shoulders, a great deal of chest showing in a way that would have had her tugging at the neckline a month ago. She isn't tugging at anything. When she leans over to hand you the mug she doesn't lean from the waist the way people do; she leans from the shoulders, so the front of the dress falls open, and she stays there a second and a half longer than the handover needs, close enough that you can feel the heat coming off her collarbones.
<<speech "Melissa">>"Come here, your collar's turned under."<</speech>>
<<speech "$name">>"It isn't. I checked it in the hall mirror on the way in, because you did this on Tuesday as well."<</speech>>
<<speech "Melissa">>"It is. Come here."<</speech>>
It isn't. You go anyway. Her fingers work at your throat, flatten down over your chest, and then simply stay — warm through the shirt, palm spread over your sternum, thumb moving in a small slow arc she doesn't appear to have authorised. Her breathing has gone shallow and high. When you look down at her hand she looks down at it too, with mild interest, like it belongs to a third party.
There's a sentence for this. A light one. It ends the whole thing and puts everybody back in their own chair, and you've had it loaded since last Tuesday.
<<speech "$name">>"Three times this week, and it was one a fortnight in the spring. I'm not complaining. I'm counting."<</speech>>
<<speech "Melissa">>"…Huh."<</speech>>
She turns that over, finds nothing in it that alarms her, and pats your chest twice like she's closing a lid. Her hand doesn't actually leave.
On the floor, the braid has stopped being a braid.
Melody still has Elsa between her knees and her hands still in her hair, but there's no braid being made and hasn't been for a quarter of an hour. She's combing through it with her fingers, over and over, and Elsa has gone loose-spined and heavy-lidded against her shins, head tipped back into her hands, mouth slightly open. Every few passes Melody's nails drag against her scalp and Elsa makes a small sound that is not quite a word, and the sound has been getting less ambiguous for about twenty minutes.
Elsa is in a cropped vest and sleep shorts at eight in the evening. She stopped bothering with anything underneath the vest nine days ago and the thin cotton makes no secret of it — her nipples are stiff enough to shadow, and the vest has ridden up under her breasts, and she does not pull it down. Her platinum hair spills over Melody's bare knees. Melody's own clip has given up entirely; golden waves down over one shoulder, blue eyes fixed on the back of Elsa's head with an intensity a hairstyle doesn't require, her skirt shoved up her thighs and her knees drifted apart on the carpet.
<<speech "Elsa">>"Don't stop."<</speech>>
<<speech "Melody">>"I wasn't going to."<</speech>>
Melody's hand slides down out of her hair, along her throat, and settles flat and open across Elsa's collarbones with her fingertips just inside the neckline of the vest. She doesn't go further. She just holds there, and Elsa arches into it, and the vest rides higher.
<<speech "$name">>"Melissa, your hand's been on my chest for about twenty minutes."<</speech>>
<<speech "Melissa">>"Has it."<</speech>>
<<speech "$name">>"What are we even watching?"<</speech>>
Three people look at the screen. Nobody answers. Elsa opens her mouth, gets a third of the way into a sentence, and simply stops — not interrupted, not distracted, arriving at the end of what she had and finding no more of it there.
<<speech "Elsa">>"…I was going to say something."<</speech>>
<<speech "Melody">>"It's alright."<</speech>>
Melissa's palm is still on your chest. Her thumb has stopped pretending to be idle and is working slow circles just below your collarbone, and she is watching her goddaughter arch into another girl's hands on the carpet with her lips parted and her chest rising visibly, and she says nothing about any of it. Nobody in this room finds any of it worth examining. The window rattles, and the evening goes on.
<<elseif _tier is 3>>
The armchair is empty and has been for a fortnight.
Melissa sits on the sofa now, on the good end, which puts you in the middle. The summer dress is open to the waist. She didn't undo it — it came open at some point last week and she never fastened it again, and so this is simply how the dress is now, hanging off her shoulders with her breasts loose inside it, heavy and flushed, the nipples dark and stiff and entirely uncovered every time she turns towards you, which is constantly.
She talks about the guttering while she does it. That's what she has instead of a way to start.
<<speech "Melissa">>"—and I said to her, well, if the man won't do the guttering himself then what //is// he for—"<</speech>>
<<speech "$name">>"Melissa."<</speech>>
<<speech "Melissa">>"Mm?"<</speech>>
<<speech "$name">>"You've been telling me about that guttering for eleven minutes and your hand is halfway down my leg."<</speech>>
She looks down at her own hand with genuine, uncomplicated interest. Then she moves it the rest of the way, cups you through the fabric, and carries on with the story with her voice only going slightly unsteady in the middle of it.
On the floor, Melody has Elsa's head in her lap and her hand is not in her hair.
Elsa is on her back across the carpet in nothing at all — the shorts came off an hour ago and nobody remarked on it — platinum hair fanned out, knees fallen wide open, and Melody has two fingers working slowly inside her while her thumb keeps up a steady pressure at the top. She's been at it long enough that the inside of Elsa's thighs are shining and the carpet under her is dark. Elsa's stomach jumps every time Melody's knuckles go deep, and her hands are up over her head gripping the leg of the coffee table, and she is breathing in short broken pulls through her mouth.
<<speech "Melody">>"He's watching."<</speech>>
<<speech "Elsa">>"Course he is."<</speech>>
<<speech "Melody">>"Should I stop?"<</speech>>
<<speech "$name">>"No. Don't stop on my account — but you can both come up here and do it where I can reach you."<</speech>>
Melody looks up. Golden hair everywhere, blouse open to the sternum, that playful little half-smile she wears in every photograph aimed at you now with nothing behind it holding it back. Her fingers don't come out of Elsa while she answers.
<<speech "Melody">>"I've been waiting a very long time for somebody to say something like that."<</speech>>
<<speech "$name">>"How long?"<</speech>>
<<speech "Melody">>"Since about April. I'd rather not be specific."<</speech>>
She withdraws her hand — Elsa makes a wrecked little noise at losing it — and comes up onto her knees in front of you. She doesn't sit on the sofa. She gets your belt open with the same unhurried competence she brings to a braid, and she puts her mouth on you like she is finally, after months, being allowed to finish something.
She's good at it in the way she's good at everything: patient, thorough, entirely unhurried. Long slow pulls with her tongue flat underneath, her golden hair falling forward until she gathers it back one-handed without breaking rhythm. Her other hand is between her own legs under her skirt and she is making small humming sounds around you that she does not appear to know she's making.
Elsa arrives a moment later, sideways, boneless, still slick to the knees, and shoulders in beside her without a word of negotiation. The two of them have shared everything since they were nine years old and they work at you the same way — no collision, no discussion, an easy instinctive division of the job. Elsa takes the base and your balls with sloppy enthusiasm while Melody keeps the head, and the two of them meet in the middle every so often and end up kissing around you with their tongues sliding together and your cock between their mouths.
Melissa has stopped talking about the guttering.
She's turned into your side with her mouth against your ear, one hand pushed inside her own dress and working, the other spread flat across your chest, and she is watching her goddaughter and her goddaughter's best friend with her pupils blown wide and her thighs pressed together.
<<speech "Melissa">>"They're being good."<</speech>>
<<speech "$name">>"They are."<</speech>>
<<speech "Melissa">>"Tell them so. They'll want to hear it from you."<</speech>>
You tell them. Elsa moans around you and Melody's rhythm falters and picks up faster, and when you finish it's across both their faces and into Elsa's open mouth, and Melissa's hand tightens hard on your chest and she comes with her forehead pressed against your temple, silently, still stroking your sternum like she's soothing a child.
Afterwards Melody licks it off Elsa's cheek without being asked, and Melissa says //good girls// in the voice she used to use about homework.
<<else>>
The living room is the warm middle of the house and the house has stopped being a house. The air is thick and sweet and slightly wrong, and none of you can smell it any more.
The television is off. The lamp with the scorch mark is the only light and it makes everything the colour of skin.
Melissa is on the sofa, naked but for the cardigan — the old one, eleven years old, hanging open off her shoulders because taking it off entirely would mean admitting there's nothing left of the woman who wore it. Dark veining runs up over her collarbones and into her hairline. Her breasts are heavy and swollen and her nipples are permanently stiff now, and her thighs are open and slick and she is not doing anything about either.
<<speech "Melissa">>"You're late."<</speech>>
<<speech "$name">>"By ten minutes. There was a queue at the crossing and I walked the long way round the green."<</speech>>
<<speech "Melissa">>"Eleven. I count them. That's what I do all afternoon — I sit in this room and count them and I can't make myself do anything else—"<</speech>>
<<speech "$name">>"You raised three children in this house."<</speech>>
<<speech "Melissa">>"//I know.//"<</speech>>
She says it like it's the worst thing anyone has ever said to her and drags you down by the front of your shirt, and she's already reaching between you to get you out and lining you up before you've got a knee onto the cushion.
You breed her on the sofa she's sat on for eleven years. She takes it with her heels locked at the small of your back and one hand clamped on the back of your neck exactly the way she's held you since you were small, and she talks the entire way through it — not dirty, that isn't in her, just the same four fragments cycling faster and faster as she gets closer.
<<speech "Melissa">>"There we are. There— //oh// —there we are, that's it, that's my— I sat up with you when you had fevers—"<</speech>>
<<speech "$name">>"I know you did."<</speech>>
<<speech "Melissa">>"—and now I can't find the rest of me, sweetheart, there's nothing else in here, there's just this and the counting, //fill me up//—"<</speech>>
She goes off around you when you empty into her, clenching hard, and afterwards she keeps her legs crossed at the ankles behind you for a full minute to hold it in. Nobody taught her that. She worked it out on her own.
On the floor, in the space between the sofa and the coffee table where they have always been, Elsa is on her hands and knees with her face down on the carpet and her hips up, and Melody is behind her with three fingers buried in her, keeping her open and ready. Elsa's hair is unbraided and always will be now. Melody stopped putting it up a month ago because there's nothing in the evening to make it neat for.
Elsa is dripping onto the carpet. There's a dark patch the size of a dinner plate underneath her and it's been growing since four o'clock.
<<speech "Melody">>"She's ready. She's been ready since four, I've had to do this twice."<</speech>>
<<speech "Elsa">>"Three times."<</speech>>
<<speech "Melody">>"Three times."<</speech>>
Elsa doesn't say anything else. She's almost entirely stopped talking — the girl who could not be quiet in this room for eleven years now manages six words an hour and spends the rest of the time looking at you with her mouth open, waiting. It's the largest single thing the parasite has taken out of this house.
Melody speaks for her.
<<speech "Melody">>"She wants to go second. She won't ask. She never asks — she gets like this and lies there and hopes somebody notices."<</speech>>
<<speech "$name">>"And you?"<</speech>>
<<speech "Melody">>"After her. Always after her."<</speech>> The little half-smile, with nothing behind it. <<speech "Melody">>"I've been in this house since I was nine and I've never once needed to be first. I like watching it happen to her. Then me."<</speech>>
You take Elsa on the carpet with Melody holding her hips steady, and she comes almost immediately and then again a minute later, silent both times, only her hands scrabbling at the carpet giving it away. Melody watches from eight inches with her hand between her own legs and her mouth open, and when you pull out of Elsa she puts her fingers straight into her and then into her own mouth.
Then Melody, on her back on the rug with her ankles by her ears and her golden hair spread out, saying //thank you// on every third thrust in the polite quiet voice she uses for absolutely everything.
From the sofa, muffled, with her hand between her own thighs again:
<<speech "Melissa">>"…I'll want it again before you go."<</speech>>
<<speech "$name">>"I know you will. You'll spend an hour not asking."<</speech>>
<<speech "Melissa">>"…Yes."<</speech>>
Outside on the main road something heavy goes past, and the window rattles in its frame, and nobody in the room so much as looks up.
<</if>>
<<case "Neighbor_House_Twins">>
<<if _tier is 0 or _tier is 1>>
The house next door has smelled the same since you were nine — cinnamon from a jar on the windowsill that never seems to empty, and old paper, because their father collected books and then died and nobody has been able to get rid of any of them.
Laila opens the door before you knock. She always does; the front window looks onto the path and she has a chair angled at it that she claims is for the light.
Long blonde hair, loose waves, a scatter of freckles across the nose that only shows properly in daylight. She's in a jumper two sizes too big with the sleeves over her hands, and the smile arrives the instant she sees who it is — that quick uncomplicated one that makes people feel like they were expected.
<<speech "Laila">>"Kettle's on."<</speech>>
<<speech "$name">>"You can't have known I was coming."<</speech>>
<<speech "Laila">>"I put it on when I see you on the path."<</speech>>
<<speech "$name">>"That's a worse answer than the one I expected, and I was expecting a bad one."<</speech>>
<<speech "Laila">>"It's //hospitality//."<</speech>>
From the kitchen doorway, flat, without looking up:
<<speech "Demi">>"It's surveillance."<</speech>>
Demi has the camera round her neck, as she has since she was fourteen. Shoulder-length hair somewhere between light brown and blonde depending on the weather, freckles heavier than her sister's, brown eyes doing that thing where they're clearly framing you before she's decided whether to lift the camera. Twins, but nobody has ever confused them for more than a second.
The front room is small and over-full. Two sofas that don't match, a coffee table with a burn ring nobody has ever apologised for, and the shoebox — the shoebox, on that table for two years — with the lid off and prints spread in a rough half-circle around it.
You sit. Tea arrives. Nobody asked whether you wanted tea. Nobody has ever asked whether you wanted tea in this house.
<<speech "Demi">>"Bottom left. That's from Tuesday."<</speech>>
Your house at dusk, taken from across the road. The kitchen window lit orange, the rest going blue, the shape of somebody moving behind the glass who is probably Elsa.
<<speech "$name">>"This is taken from your front window."<</speech>>
<<speech "Demi">>"It's taken from the good chair."<</speech>>
<<speech "Laila">>"//Demi.//"<</speech>>
<<speech "Demi">>"He asked. I'm not going to lie about a chair."<</speech>>
Two years of this now — the street, the gardens, the same six houses in every light there is. She's genuinely good. That's the thing nobody in either family quite says out loud: the photographs aren't a hobby, they're better than they need to be, and she keeps them in a shoebox.
Further down, under the recent ones, the prints get older. Rounder corners, different paper. There's one of a garden with three children in it, two of them you and Elsa, and a woman in the background out of focus who has been dead eleven years.
Nobody says anything about that one. Laila puts her hand flat on the table beside yours, not touching it, and leaves it there until you've finished looking and put the print back.
<<speech "Laila">>"Stay a bit. You don't have to talk."<</speech>>
<<speech "$name">>"I know. That's why I keep turning up."<</speech>>
<<speech "Demi">>"That's the actual draw. Not the tea."<</speech>>
<<speech "Laila">>"The tea is //also// a draw."<</speech>>
<<speech "Demi">>"The tea is fine, Laila."<</speech>>
<<speech "Laila">>"//Fine//, she says. In my own house."<</speech>>
<<elseif _tier is 2>>
The good chair has moved.
It used to sit square to the front window. It now sits at the end of the sofa, angled in, close enough that Laila's knee touches your leg the whole time she's in it — and when you pointed this out three weeks ago she said, entirely openly, that the light was better there. The light is not better there. She knew that when she said it, and said it anyway, and poured the tea.
She's in a vest under an open cardigan tonight and the cardigan has been sliding off the same shoulder all evening. When she leans across to top up a cup that doesn't need it, the vest hangs open and there's nothing under it, and she takes considerably longer over the pouring than it requires. It has happened four times. Each time she straightens up she looks at your face rather than the cup, to see.
<<speech "Laila">>"Sugar?"<</speech>>
<<speech "$name">>"I've never taken sugar. Not once, in about fifteen years of this."<</speech>>
<<speech "Laila">>"I know. I like asking."<</speech>>
She sits back down and her hand ends up on your forearm and stays there, warm, thumb moving. Then it's on your knee. Then it isn't on your knee, it's a good deal further up your thigh, and she carries on talking about somebody's guttering the entire time as if her arm belongs to a different conversation.
There's a light sentence available for this — the kind that turns it into a joke and puts the chair back by the window. It's been loaded and ready since last week.
<<speech "$name">>"You've moved that chair about four feet in a month."<</speech>>
<<speech "Laila">>"Have I?"<</speech>>
<<speech "$name">>"You have. I'm not asking you to move it back."<</speech>>
<<speech "Laila">>"…Alright."<</speech>>
Her hand goes the rest of the way and settles over you through your jeans, and she leaves it there, and her thumb starts moving in the same absent way it did on your forearm.
Across the room the shutter goes.
It has gone perhaps nine times this evening. Demi is on the arm of the other sofa with one leg crossed over the other, camera up, and she is not photographing the street. She hasn't photographed the street in weeks. Her knee is bouncing and she's shifted position three times in as many minutes.
<<speech "$name">>"You did it again."<</speech>>
<<speech "Demi">>"I photograph everything. You've known me since I was nine. This is the least surprising thing about me."<</speech>>
<<speech "$name">>"What's in the box these days?"<</speech>>
<<speech "Demi">>"The block."<</speech>>
<<speech "$name">>"Can I look?"<</speech>>
A pause about a second and a half too long. Her thumb moves on the camera body.
<<speech "Demi">>"…Not the top layer."<</speech>>
<<speech "Laila">>"//Demi.//"<</speech>>
<<speech "Demi">>"I said not the top layer! That's all I said! Why is that the sentence you've decided to be scandalised by—"<</speech>>
<<speech "Laila">>"Because you're being strange about it, and it's making //me// look normal, and I'm not, I've got my hand on him—"<</speech>>
They both stop at once, at exactly the same instant, the way they have done since they were small.
It sits in the middle of the room for a couple of seconds, completely visible, nobody looking at it. Then Laila picks up the teapot with her free hand — the other one does not move — and Demi lifts the camera, and the whole thing closes over without either of them examining it.
<<speech "Laila">>"More tea?"<</speech>>
<<speech "$name">>"Go on, then."<</speech>>
The shutter goes again.
<<elseif _tier is 3>>
Nobody makes tea. The pot is where it was left on Sunday, the kettle is cold, and the good chair is empty because Laila has stopped using any furniture that isn't the sofa you're on.
She's straddling your lap, cardigan gone, vest pushed up under her arms so her breasts are out, and she's kissing you the way she does everything in this house — completely, generously, arranged entirely around what the other person might want.
<<speech "Laila">>"Is this alright? Tell me if it's too—"<</speech>>
<<speech "$name">>"Laila. You've asked me that four times in six minutes."<</speech>>
<<speech "Laila">>"I know I have. I can't work out how to stop, it's the only way I know how to—"<</speech>>
<<speech "$name">>"Then ask less and use your mouth more."<</speech>>
<<speech "Laila">>"//Yes.//"<</speech>>
She's off your lap and onto her knees on the rug with the same brisk competence she brings to a kettle. The noise she makes when she gets your belt open is pure uncomplicated relief — a woman who has spent her whole life putting things in front of people finally handed something she's allowed to want.
She's not skilled. She's enthusiastic and slightly clumsy and she keeps going too deep too early and having to come off coughing, blonde hair stuck to her wet chin, freckles lost in a flush that's gone to her collarbones — and then straight back down, because stopping isn't in her. Her free hand is up under her own skirt and moving fast.
The shutter goes. Twice.
<<speech "$name">>"Demi."<</speech>>
<<speech "Demi">>"Don't."<</speech>>
<<speech "$name">>"Put it down."<</speech>>
<<speech "Demi">>"//Don't.//"<</speech>>
Her voice isn't steady. Behind the viewfinder her jaw is tight and her eyes are wet and the freckles have vanished into a flush all the way down.
<<speech "Demi">>"If I'm holding it, I'm working. I'm //documenting//. That's a thing I'm allowed to do in this room. If I put it down I'm just — I'm in it."<</speech>>
<<speech "$name">>"You've been behind that thing since you were fourteen. Put it down and come here."<</speech>>
She sits perfectly still for three seconds. Then she sets the camera on the sofa arm — still running, still pointed at the three of you — crosses the room, and kneels on the rug beside her sister without another word.
<<speech "Laila">>"There you are."<</speech>>
<<speech "Demi">>"Don't."<</speech>>
<<speech "Laila">>"I've been saying for //weeks//—"<</speech>>
<<speech "Demi">>"Laila, I will end you."<</speech>>
<<speech "$name">>"Both of you. Together, and stop talking."<</speech>>
They go quiet and do as they're told, and they work like twins — no negotiating, no collisions, an instinctive knowledge of where the other one is that they've had since before they could speak. Laila takes the base with both hands and her whole open enthusiasm; Demi is precise, working the head with the flat of her tongue in short controlled strokes, brown eyes up on your face the entire time, checking the effect of everything she does. Between them they take about ninety seconds to reduce the situation to its component parts.
When you finish it goes across both their mouths and Demi's cheek. Laila immediately, without any prompting, leans across and licks her sister's face clean, and Demi lets her, and neither of them treats this as remarkable.
Afterwards, still on the floor, Demi reaches up without any apparent irony and adjusts the camera on the sofa arm by about two degrees.
<<speech "Laila">>"You did //not//—"<</speech>>
<<speech "Demi">>"The framing was off."<</speech>>
<<speech "Laila">>"The //framing//—"<</speech>>
<<speech "Demi">>"It's for the box."<</speech>>
<<else>>
The house still smells of cinnamon. That's the part that doesn't sit right — underneath everything else, the jar on the windowsill is still doing its job.
There are two shoeboxes on the coffee table now. The first one is full. Neither contains a photograph of the street.
They don't get up when you come in; they felt the gate. Both heads come round at the same instant with the same tilt, which they've done their entire lives and which used to be charming.
<<speech "Laila">>"Kettle's on."<</speech>>
<<speech "Demi">>"The kettle is not on. The kettle hasn't been on in a month."<</speech>>
<<speech "Laila">>"…No. Sorry. I still say it."<</speech>>
<<speech "Demi">>"She says it every time. It's the last bit of her that's left and it's //that//."<</speech>>
Laila is in the cardigan and nothing else, sat forward on the sofa with her knees apart and one hand already between them, blonde hair pushed behind her ears. Demi is on the rug with the camera strap round her neck and a shirt hanging open — both still wearing something, because being entirely naked in the front room they grew up in would be an admission neither will make.
Dark veining climbs Laila's throat. Demi's is across her ribs. She has photographed it, repeatedly, from several angles.
<<speech "Laila">>"Me first. Please. I've been sat here since two."<</speech>>
<<speech "Demi">>"She has. Timestamps."<</speech>>
<<speech "$name">>"Of course there are timestamps."<</speech>>
<<speech "Demi">>"It's for the box."<</speech>>
<<speech "$name">>"There's no project any more, Demi. There hasn't been since October."<</speech>>
<<speech "Demi">>"…There's a box."<</speech>>
You breed Laila on the sofa you've sat on since you were nine. She holds your face in both hands the whole way through and asks, over and over, in a voice with nothing left in it but the asking, whether it's alright — whether she's doing it right, whether you're comfortable, whether there's anything else she can do. She comes twice and apologises for the second one.
<<speech "Laila">>"Is it alright? Tell me it's—"<</speech>>
<<speech "$name">>"It's alright. You've never once done it wrong, in eleven years, not once."<</speech>>
<<speech "Laila">>"Then don't stop. I'll do anything, I'll do //anything//, just tell me what and I'll—"<</speech>>
She loses the sentence in the middle and starts it again from the top about a minute later, and she's still going when you empty into her, and she goes quiet then and holds her knees to her chest afterwards without being told.
Demi shoots the whole thing. Then she takes her turn on the rug by the table, on her back, holding the camera above her in both hands and shooting up at you the entire time — narrating in flat fragments about the light and the angle, because the alternative is having nothing between herself and this.
<<speech "Demi">>"Hold— hold still, the light's going, it goes at four and I can't—"<</speech>>
<<speech "$name">>"Put it down, Demi."<</speech>>
<<speech "Demi">>"//No.//"<</speech>>
<<speech "$name">>"Put it down and look at me instead."<</speech>>
She holds out four more seconds. Then the camera goes down onto the rug beside her head, still running, still pointed at the ceiling, and both arms come up round your neck and pull you all the way down — and for the first time since she was fourteen there is nothing between Demi and the thing she is looking at. She comes almost immediately and makes an appalling amount of noise about it, which her sister finds delightful.
She lies there a long while afterwards with one hand flat on her own stomach and the other resting on the camera body, not lifting it.
<<speech "Demi">>"…That would have been a good one."<</speech>>
<<speech "Laila">>"You didn't take it."<</speech>>
<<speech "Demi">>"I know."<</speech>>
<</if>>
<<case "Cousin_Family">>
<<if _tier is 0 or _tier is 1>>
The living room feels familiar and slightly tense, the way family gatherings always do when people who share childhood memories but not daily life try to occupy the same space. Winter is working on her laptop at the table, her presence commanding even in silence. She's the oldest cousin, law school and distance making her a stranger to the younger ones, but family is family. Her straight light brown hair falls in a severe line, her blue eyes scanning documents with the efficiency of someone who doesn't have time for small talk. Her fair skin is pale under the harsh light, her medium breasts hidden beneath a tailored blouse, her bright smile rare but genuine when it appears.
<<speech "Winter">>"The precedent was set in 2014, but the defense is arguing—"<</speech>> She mutters to herself, then catches herself, looks up, remembers where she is. <<speech "Winter">>"Sorry. Habit."<</speech>>
Lana lounges on the couch, flipping through her phone, her confidence filling the room even in repose. She's Winter's younger sister, Kylie's older sister, the middle child in every way that matters—outspoken, teasing, fiercely protective beneath the sarcasm. Her brown hair falls past her shoulders, lighter at the ends from sun, her blue eyes sharp even when apparently distracted. She's fair-to-medium skinned, her big breasts and big ass displayed confidently in fitted jeans and a tight top.
<<speech "Lana">>"She's always like this. Objectively terrible at vacations,"<</speech>> Lana says, not looking up from her phone, her teasing automatic.
Kylie is excitedly pulling out an old photo album from the cabinet, her petite frame vibrating with energy. She's the youngest, playful and lively, always up for something, always moving. Her dark brown hair is in a ponytail that swings with every movement, her light skin glowing with health, her wide smile infectious. She wears a sundress that shows off her petite body, her small breasts and slim hips moving as she bounces on her toes.
<<speech "Kylie">>"Look at this one! Summer at the lake, remember?"<</speech>> She holds up the album enthusiastically, her cheerfulness filling the room. <<speech "Kylie">>"We were all so young! And look at Winter's face!"<</speech>>
<<speech "Lana">>"I remember. I looked ridiculous in that hat. Put it away,"<</speech>> Lana replies, though she's smiling, her teasing covering genuine affection.
Winter glances over from her laptop, sharp as ever, her blue eyes assessing the photo with legal precision. <<speech "Winter">>"The hat was terrible. Objectively. And Kylie, you're blocking the light."<</speech>>
<<speech "Lana">>"It was in style!"<</speech>> Lana protests, laughing.
<<speech "Kylie">>"It really wasn't,"<</speech>> Kylie giggles, her ponytail swinging.
<<speech "Lana">>"$name, back me up here!"<</speech>> Lana appeals to you, her confidence making it a command rather than a request.
Winter closes her laptop with a decisive click, her efficiency making even relaxation scheduled. <<speech "Winter">>"He has better taste than to lie for you. And we should focus. Family dinner is in two hours, and I have work to finish."<</speech>>
But she doesn't open the laptop. She stays, watching her younger cousins, her sharp expression softening almost imperceptibly. Family is family, and she keeps an eye on them, even from a distance, even when she pretends not to care.
The afternoon stretches—Kylie's energy, Lana's teasing, Winter's sharp commentary, you moving through it all as the cousin they grew up with, the one who knows their patterns. It's familiar. It's slightly tense. It's family.
<<elseif _tier is 2>>
The living room is different today. The afternoon light is the same, but the air is thicker, warmer, charged with something that makes the skin prickle. Winter is at the table, but her laptop is closed, her blouse unbuttoned to show her medium breasts in a lace bra, her fair skin flushed, her straight light brown hair falling forward as she leans over documents she can't focus on.
<<speech "Winter">>"I've been… distracted. It's annoying. I can't focus on work,"<</speech>> She admits, her sharp efficiency cracking, her blue eyes glazed as they find you. <<speech "Winter">>"I keep thinking about—no. I shouldn't. You're my cousin. But I can't stop."<</speech>>
Lana is on the couch, her phone forgotten, her tight top now revealing her big breasts, her jeans unbuttoned, her big ass pressing against the cushions as she shifts restlessly. Her confidence has become desperation, her teasing turned to begging.
<<speech "Lana">>"There you are. Took you long enough,"<</speech>> She says, trying to sound teasing but her voice comes out breathy, her hand resting on her own thigh, fingers tracing patterns. <<speech "Lana">>"I've been thinking about you. About touching you. About—"<</speech>> She stops, gasping, her hips bucking slightly against the couch.
Kylie is on the floor, her sundress hiked up, her petite body flushed, her light skin marked with desire. Her ponytail has fallen out, her dark brown hair wild, her wide smile replaced by an open mouth, her hand between her legs, pressing through her panties.
<<speech "Kylie">>"It's weird… I keep feeling really warm whenever you're around lately,"<</speech>> She says, her voice high and breaking, her hips rocking against her hand. <<speech "Kylie">>"I keep thinking about you touching me. About both of them touching me. About—"<</speech>> She comes with a gasp, her body convulsing, her face contorted with pleasure she doesn't understand.
<<speech "Lana">>"Distracted? You've been staring at $name for five minutes straight,"<</speech>> Lana teases, though she's biting her lip and shifting uncomfortably, her own hand now inside her jeans.
Winter shoots her a sharp look, but her cheeks are visibly red, her hand now on her own breast, squeezing through her blouse. <<speech "Winter">>"I'm supposed to be the responsible one. The efficient one. And I can't stop—"<</speech>> She stops, her hips bucking against the chair, her legal mind silenced by physical need.
The three of them surround you, Winter's hand stroking you through your pants with efficient thoroughness, Lana's hand joining hers with teasing confidence, Kylie watching with glazed eyes, her hand still between her legs. The living room has become a hothouse, the family space corrupting, the cousin dynamic dissolving into something else entirely.
<<elseif _tier is 3>>
The living room has become a sanctuary of sex, the afternoon light golden and obscene, the air thick with pheromones. Winter is on her knees, her blouse gone, her medium breasts exposed, her fair skin flushed with dark veining. Her efficiency has been completely rewritten into desperate service, her legal mind now devoted entirely to pleasing you.
<<speech "Winter">>"Master—"<</speech>> The word escapes her, and she freezes, her blue eyes wide, but she doesn't take it back. <<speech "Winter">>"Please, Master. Let me show you how thorough I can be."<</speech>>
She takes you into her mouth with the thoroughness she brings to everything, her straight light brown hair falling forward, her medium breasts pressing against your thighs, her tongue skilled and desperate. She's the oldest, the responsible one, and she applies herself completely to this new purpose.
Lana is beside her, her big breasts hanging, her jeans gone, her big ass presented, her confidence completely transformed to begging. <<speech "Lana">>"I used to tease you so much, Master. I used to poke fun. Now I just want to be your teasing little slut. Please, Master. Let me make up for it. Let me show you how good I can be."<</speech>>
She takes you from Winter, her mouth replacing her sister's, her confidence making her sloppy and eager, her big breasts pressing against your other thigh, her blue eyes looking up with devotion that terrifies her even as she feels it.
Kylie is between your legs, her petite body naked, her dark brown hair wild, her light skin marked with desire. Her playfulness has become pure sexual enthusiasm, her lively energy channeled into desperate service.
<<speech "Kylie">>"I can't stop thinking about you touching me, Master,"<</speech>> She whispers, her voice high and breaking, her small breasts pressing against your leg.
The three of them share you, passing your cock between their mouths, their faces pressed together, tongues sliding over each other, over you. Winter's efficiency makes her thorough. Lana's confidence makes her bold. Kylie's playfulness makes her enthusiastic. The three cousins, reduced to the same desperate need to serve their Master.
You come, spilling over their faces, their open mouths, their waiting tongues. They fight to catch it, to share it, their devotion complete, their previous relationships—sisters, cousins—all transformed to collaboration in your service, all calling you Master, all completely possessed.
<<else>>
The cousin's house has been fully claimed. The living room is stained, the air thick, the afternoon light turned golden and obscene. Winter, Lana, and Kylie kneel submissively as you enter, completely naked, bodies marked with dark veining, pussies swollen and constantly leaking, bellies softly rounded from previous breedings. Their common sense is gone, their family bonds transformed to breeding devotion.
<<speech "Winter">>"Welcome back, Master,"<</speech>> Winter says, her sharp, serious personality now fully surrendered, her medium breasts hanging, her straight light brown hair tangled, her blue eyes glazed with devotion. <<speech "Winter">>"We've been keeping our wombs warm for you all day, Master. I've scheduled everything around your arrival. Please, Master. Breed us. Please make us pregnant again, Master."<</speech>>
Lana purrs, spreading her legs shamelessly, her big breasts marked with your handprints, her big ass presented, her confidence completely transformed to desperate submission. <<speech "Lana">>"Please, Master. Breed me. Make me carry your child. Make me your teasing little broodmare, Master."<</speech>>
<<speech "Kylie">>"Me too, Master! I want to carry your babies so bad!"<</speech>> Kylie says excitedly, crawling closer, her petite body shaking with need, her dark brown hair wild, her light skin flushed. <<speech "Kylie">>"I want to have the ultimate adventure, Master! I want to be pregnant with your child! Please, Master! Make me your playful little breeding whore, Master!"<</speech>>
<<speech "Winter">>"Stop competing and serve him properly,"<</speech>> Winter tells the younger two, though her voice is thick with lust, her efficiency making her organize even in desperation. <<speech "Winter">>"We exist for $name now, Master. All three of us. Your efficient slut, your teasing slut, your playful slut. Please, Master. Use us. Breed us. Make us your family of breeding whores, Master."<</speech>>
The three corrupted cousins press against you, eager to worship and be filled again—Winter's thoroughness making her position herself perfectly, Lana's confidence making her bold in her begging, Kylie's playfulness making her bounce with desperate energy. They suck, they stroke, they present themselves, their previous relationships—sisters, oldest, middle, youngest—all transformed to collaboration in your service, all calling you Master, all begging to be bred.
You take Winter first, her efficiency making her hold you deep, her medium breasts bouncing, her body milking you desperately. She comes silently, her legal mind completely destroyed in total possession. <<speech "Winter">>"Master… thank you… for breeding your efficient little slut…"<</speech>>
Lana next, her confidence completely broken, her big breasts pressed to the floor, her big ass shaking as you pound her. <<speech "Lana">>"Master… thank you… for breeding your teasing little slut… thank you for making me useful, Master…"<</speech>>
Kylie last, her playfulness completely channeled into sexual enthusiasm, her petite body taking you deep, her small breasts swaying. <<speech "Kylie">>"Master… thank you… for the ultimate adventure… thank you for making me pregnant, Master…"<</speech>>
Afterwards, the three of them lie together on the breeding floor, cum dripping from them, bellies softly rounded, faces flushed with devotion—oldest, middle, youngest, all reduced to the same thing: warm, willing, breeding flesh, grateful to serve their Master.
<</if>>
<<case "Eva_House_Standard">>
<<if _tier is 0 or _tier is 1>>
Eva has been $name's best friend since school and the arrangement they have arrived at is that he does not knock. He lets himself into the house she shares with her sisters, and this evening the three of them are in the front room fighting about what to watch, which is how most evenings here begin.
Eva is lengthwise on the couch and has taken all of it. She's tall, dark-haired, freckled across the nose, built by the amount of time she spends in a gym, and she moves her feet perhaps two inches to let him sit down. That is the entire greeting. Neither of them has ever needed more than that.
Harmony is on the floor in front of the couch inside a blanket she has folded round herself so only her hands and most of her face are available. She's the youngest, small and dark-eyed, and she is watching her older sister for cues in the way she always does.
Alina has the armchair, the remote, and a laptop open on the chair arm that she is pretending not to work on. She's the eldest, green-eyed, heavy dark eyeliner, and she runs the small-group sessions at the gym, which means she knows everybody in town and everybody's business along with them.
<<speech "Alina">>"Horror, comedy, or documentary."<</speech>>
<<speech "Eva">>"Horror."<</speech>>
<<speech "Harmony">>"Comedy!"<</speech>>
<<speech "Alina">>"Documentary."<</speech>>
<<speech "Eva">>"Right. Tiebreaker."<</speech>>
She prods $name in the thigh with her foot and then leaves the foot there, the way she has since they were both fifteen.
<<speech "$name">>"Absolutely not. Last time I picked, Harmony wouldn't speak to me."<</speech>>
<<speech "Harmony">>"I spoke to you! I just didn't say anything //nice//."<</speech>>
<<speech "$name">>"You said 'fine' to me twice and then went upstairs."<</speech>>
<<speech "Eva">>"He's useless. He's been useless at this his whole life."<</speech>>
<<speech "$name">>"You pick the film every single time and then pretend to consult me about it."<</speech>>
<<speech "Eva">>"Yes. And you keep sitting down anyway."<</speech>>
Alina looks up from the laptop with the particular brightness of a woman about to deploy something she has deployed many times before.
<<speech "Alina">>"I've seen married couples banter far less. You know, if things ever go badly with Aria — you did pick the wrong girlfriend."<</speech>>
<<speech "Eva">>"Oh, //here// we go."<</speech>>
<<speech "Alina">>"I'm only saying. He's here more than you are. He knows where the mugs live."<</speech>>
<<speech "Harmony">>(delighted, only her eyes visible) "She's doing it again!"<</speech>>
<<speech "Eva">>"You're my sister. You're meant to be on my side."<</speech>>
<<speech "Alina">>"I am on your side. That's why I'd like you to have him."<</speech>>
The pillow catches her on the shoulder and knocks the laptop halfway off the chair arm. She saves it without appearing to move and puts the pillow behind her own back where Eva can't reach it.
None of this lands anywhere. It never does. Eva and $name have known each other too long and too plainly for it to be anything but an old family joke that Harmony finds funny and Eva finds tiring, and the proof is that thirty seconds later Eva is arguing with him about the same film they always argue about, and has put her feet back in his lap without either of them registering it.
<<speech "$name">>"Fine. Documentary. Tell me what it's actually about before I agree."<</speech>>
<<speech "Alina">>"Octopuses."<</speech>>
<<speech "Eva">>"This is my life. Octopuses and matchmaking."<</speech>>
They watch the octopuses. Harmony falls asleep partway through with one hand still in the popcorn bowl. Eva talks over most of it. Alina goes back to the laptop and only surfaces for the part with the coconut shells, and then makes everybody rewind it.
<<elseif _tier is 2>>
The house has been warm all day and it is not the weather. It sits close and sweet at the back of the throat, and all three of them have been living in it since morning without ever quite saying so.
The film is on and no one is watching. Eva is up off the couch before he's properly through the door, which is not what she does, and she doesn't manage to make it look like anything else.
<<speech "Eva">>"You took your time."<</speech>>
<<speech "$name">>"I'm here at the same time I always am."<</speech>>
<<speech "Eva">>"I know. It felt longer. It's been feeling longer all week."<</speech>>
She's in shorts and one of her own old shirts and she has been shifting on that couch for an hour, and when she gets a hand on his arm she doesn't take it back off. There is something faintly frightening in how directly she's looking at him, because Eva has never once looked at him like that and they both know it.
Alina is against the doorframe in the kit she came home in, hair still up off her neck, and she has stopped bothering to disguise where she's looking.
<<speech "Alina">>"It isn't only her. I couldn't focus at work today. Two clients and I couldn't tell you a single thing either of them did."<</speech>>
<<speech "$name">>"You've never lost track of a session in your life."<</speech>>
<<speech "Alina">>"No. Which is why I mention it."<</speech>>
She says it levelly. Then her mouth stays open a moment on nothing at all, and she closes it.
Harmony has the blanket but she's holding it round herself rather than sitting in it, knees drawn up, rocking very slightly without knowing she's doing it.
<<speech "Harmony">>"I feel hot all the time. It won't go away and I don't know how to say it without sounding —"<</speech>>
<<speech "Eva">>"Sounding what? I'm sat here soaked through my shorts."<</speech>>
<<speech "$name">>"Leave her alone. She's the only one still trying to be polite about it."<</speech>>
Eva laughs and it comes out wrong — too high, and cut off short. She has hold of his shirt with two fingers now, the way you'd hold something to stop it drifting off.
<<speech "Eva">>"I'd do anything for you. You know that. I've always known that and it never meant //this//."<</speech>>
<<speech "$name">>"And now?"<</speech>>
<<speech "Eva">>"Now I keep thinking about it meaning this and I can't put it down. Please don't make me explain it better than that."<</speech>>
Alina pushes off the doorframe, crosses the room, and stops closer than she needs to.
<<speech "Alina">>"That joke I make about you picking the wrong girlfriend."<</speech>>
<<speech "$name">>"You've made it since we were at school."<</speech>>
<<speech "Alina">>"I'd like to withdraw it. Not because it was wrong. Because I meant it about her and now I don't."<</speech>>
Behind them the film carries on to nobody. Harmony has both hands inside the blanket and has stopped pretending otherwise.
<<elseif _tier is 3>>
The television is still on and the sound is still up and nobody has been near the remote.
Eva doesn't say anything when he comes in. She crosses the room and goes down onto her knees on the rug and gets his belt open with her hands shaking, and she is not looking at him while she does it.
<<speech "Eva">>"Don't talk to me for a minute."<</speech>>
<<speech "$name">>"You're the one who talks. You've never gone quiet in your life."<</speech>>
<<speech "Eva">>"I know. Please. Just a minute."<</speech>>
She takes him in her mouth like she's been holding her breath since morning, and after that she does go quiet, apart from sounds she is plainly not choosing to make.
Alina comes down beside her with none of the composure she has spent her whole life assembling. She kneels the way she'd kneel to fix somebody's form, which is somehow worse, and puts a flat hand on Eva's back.
<<speech "Alina">>"Slower. You'll wreck your jaw and then it's me on my own."<</speech>>
<<speech "Eva">>(off him, wrecked) "Then //help//."<</speech>>
<<speech "Alina">>"I'm going to. I'd like it noted that I asked nicely first."<</speech>>
<<speech "$name">>"Both of you. Neither of you is arguing your way out of this one."<</speech>>
She does, and she's unhurried and thorough, and every so often she stops to say something and can't find the end of it.
Harmony is still on the floor by the couch with the blanket half off her shoulders, watching, one hand moving underneath it, her whole face burning.
<<speech "Harmony">>"Can I — is it all right if I —"<</speech>>
<<speech "$name">>"Come here, Harmony. You've been sat on that floor watching this whole time."<</speech>>
<<speech "Eva">>(surfacing, hoarse and thrilled) "She's been practising. Ask her what she's been practising on."<</speech>>
<<speech "Harmony">>"Eva!"<</speech>>
<<speech "$name">>"Ignore your sister. Nobody in this room is in any position to judge anybody."<</speech>>
She comes over on her knees, careful and nervous, and immediately makes a sound she did not plan to make. Alina's hand goes into her hair and stays there, steady, the way it has since Harmony was small.
<<speech "Alina">>"There. Breathe through your nose, cariño."<</speech>>
The three of them take him in turns with the film still running behind them, and not one of them looks at it.
<<else>>
The front room has stopped being a front room. The couch cushions are on the floor, the blanket is somewhere underneath them, and the television has gone to its menu screen and is looping the same few seconds of music that nobody has got up to stop.
They're on the rug when he comes in. Eva up on her knees, Alina sat back on her heels, Harmony flat on her stomach with her chin on her folded arms — three Latina women who between them have never once in their lives waited for anything, waiting.
<<speech "Eva">>"There he is. God, I've been empty since this morning."<</speech>>
<<speech "$name">>"You've had a whole day to yourself. You survived it somehow."<</speech>>
<<speech "Eva">>"It was the worst day of my life and I want that taken seriously."<</speech>>
You take her over the arm of the couch and she braces on her forearms and swears steadily into the upholstery, and comes without any of the bravado she has carried since she was a girl.
<<speech "Eva">>"Fill me. Please. I want it to take this time, I want to be the first one —"<</speech>>
<<speech "$name">>"Hold still and stop swearing at the furniture."<</speech>>
Harmony crawls up the rug without being asked and puts her mouth where the two of them meet, and Eva's voice goes entirely.
<<speech "Harmony">>(surfacing, wet-faced and shining) "Me next. Please. I waited, I've been so good about waiting —"<</speech>>
<<speech "$name">>"You were. Get up on the couch and put your legs round me."<</speech>>
She takes it on her back with her heels locked behind him and says please the whole way through, and it stops being a word somewhere in the middle.
Alina waits, because Alina is the eldest and waits, and when it's her turn she goes face down over the couch arm and reaches back to guide him in herself.
<<speech "Alina">>"I said you picked the wrong girlfriend. I said it for years."<</speech>>
<<speech "$name">>"To anybody who'd listen, and plenty who wouldn't."<</speech>>
<<speech "Alina">>"I was aiming too low. Breed all three of us and I'll never have to make the joke again."<</speech>>
Afterwards the three of them stay on the rug, leaking, unhurried, arranged around him the way they arrange themselves for a film. The menu screen loops its few seconds of music. Nobody gets up.
<</if>>
<<case "Mansion_Standard">>
<<if _tier is 0 or _tier is 1>>
The mansion is the largest house in the town by a wide margin and Haley is giving the tour again. She gives it every time and she is aware she gives it every time, and she has started adding things to keep herself interested.
<<speech "Haley">>"And //this// is the library. It's bigger than most people's houses."<</speech>>
She says it with both arms out. There are perhaps nine hundred books and a ladder on a rail that she pushes about four feet along its track for the effect, and then has to walk back to.
Casey is on the sofa by the window with a book face down on her knee, not reading it, and has been in that position for the entire tour.
<<speech "Casey">>"Generous. You've read about ten books in this room, total."<</speech>>
<<speech "Haley">>"Nobody asked you, Casey."<</speech>>
She turns her back on the sofa in a big deliberate movement and smiles at $name like the sofa is not there.
<<speech "Haley">>"Ignore her. She's like this with everyone, it isn't personal."<</speech>>
<<speech "$name">>"It's a bit personal, Haley. She's looked at me twice and neither was friendly."<</speech>>
<<speech "Casey">>"It's a bit personal."<</speech>>
The room is cold. That's the thing that isn't in the tour — the radiators are on in about a third of the house and this isn't one of the thirds, and there's a smell of unaired room under the polish. Two doors off the corridor have been shut a long time.
Luna comes in from the garden with a trug of cut stems and secateurs, and doesn't announce herself. She sets the trug down and starts sorting stems into a jug she has carried in for the purpose, snipping ends at an angle, working while she talks.
<<speech "Luna">>"You're Haley's friend. You've been here a few times now."<</speech>>
<<speech "$name">>"Four. Five if the party counts, and I'd rather it didn't."<</speech>>
<<speech "Luna">>"Five. You're the first one she's brought back more than once."<</speech>>
<<speech "Haley">>"//Mom.//"<</speech>>
Luna doesn't look up from the jug. She takes about six inches off a stem that didn't need it.
<<speech "Casey">>"He's not like the others. The ones who come for the money."<</speech>>
She has finally looked up from the book she isn't reading, and the look is a long one and lands square.
<<speech "Casey">>"He's Lana's cousin."<</speech>>
<<speech "$name">>"That's the whole endorsement, is it. Related to someone you like."<</speech>>
<<speech "Casey">>"From me it's an enormous one. Don't push it."<</speech>>
Luna turns the jug a quarter turn, considers it, and pulls one stem back out.
<<speech "Luna">>"People are complicated. There's a difference between complicated and after something."<</speech>>
She sets the jug on the sill where the light gets at it, and gathers the offcuts into her palm, and only then does she actually look at him properly.
<<speech "Luna">>"You're welcome here. Any time. That's not a formality, I'd like you to actually use it."<</speech>>
<<speech "$name">>"I'll use it. This house has better heating in one room than mine has in all of it."<</speech>>
<<speech "Luna">>(the smallest possible smile) "That's the first honest compliment anybody's paid this house in a year."<</speech>>
Haley moves the ladder another four feet, on principle, and has to walk back to it again.
<<elseif _tier is 2>>
The house has been warm for days, which it never is, and it isn't the radiators. It sits at the back of the throat, thick and sweet, and it is strongest in the rooms they actually use.
Luna is at the sill with the jug. She has cut fresh stems and she is doing them one at a time, slowly, and getting most of them wrong — too short, all the same height, none of the angles she'd normally take trouble over. She keeps stopping with the secateurs in her hand and looking at nothing.
<<speech "Luna">>"There's a warmth in this house lately. It's been years since it was warm."<</speech>>
<<speech "$name">>"It isn't the house. The radiators are off in this wing, they always have been."<</speech>>
<<speech "Luna">>"No. I know that. I'm choosing to describe it as the house."<</speech>>
When he comes to stand beside her she leans into it — the whole side of her body against his — and keeps snipping stems, badly, and doesn't move away.
Haley has stopped doing the tour. She's sitting on the arm of the sofa with her feet on the cushions, which Casey would normally object to, and Casey has not objected.
<<speech "Haley">>"Why does it get //hot// when you come in? It does. I've started noticing it in the hall before I've seen you."<</speech>>
<<speech "$name">>"You've started listening for the door. That's what that is."<</speech>>
<<speech "Haley">>"I've started listening for the //car//. It's worse than that."<</speech>>
She isn't embarrassed about it. That's the shift. Six months ago she'd have said it as a joke and covered it, and now she says it and then just looks at him, waiting to see what he does with it.
Casey has the same book on her knee, still face down, and the page has not changed in an hour. Her blouse is undone a button further than she would ever leave it and she is sitting very upright, which is what Casey does instead of admitting anything.
<<speech "Casey">>"I've been uncomfortable all day."<</speech>>
<<speech "$name">>"'Uncomfortable.' That's a very Casey way of putting it."<</speech>>
<<speech "Casey">>"It's the accurate way of putting it. My body keeps — reacting. To nothing. To you crossing a room."<</speech>>
He crosses the room. She watches him do it the entire way and doesn't uncross her legs and doesn't look away, and when he puts a hand on the back of her neck she shuts her eyes and lets her head go forward and says nothing at all for a while.
Luna's hand stops on the secateurs. It takes her completely — a sharp inward breath, her knuckles white on the handles, her whole body going rigid against his side for four or five seconds. Then it lets go. She looks down at the jug, and at the stem she's holding, and cannot place it.
<<speech "Luna">>"…I'm sorry. What was I doing?"<</speech>>
<<speech "$name">>"The flowers. You've cut them all the same length."<</speech>>
<<speech "Luna">>(looking at them, unbothered) "So I have. It doesn't matter."<</speech>>
She puts them in the jug anyway.
<<elseif _tier is 3>>
They use the drawing room now, which is a room nobody has used for anything in years and which is finally, properly warm.
Luna is first, and she is first because she asks — not desperately, just plainly, the way she'd ask anyone to stay for dinner.
<<speech "Luna">>"May I."<</speech>>
<<speech "$name">>"You don't have to ask. Not here. It's your house, Luna."<</speech>>
<<speech "Luna">>"I'd like to. I've asked for very little in this house for a long time."<</speech>>
She kneels on the rug with the same unhurried care she brings to the flowers, and she takes her time, and her eyes stay up. There's nothing frantic in it anywhere. When she comes off him she rests her forehead against his hip for a second before she goes back.
Haley arrives at speed and drops down next to her, and she is grinning, and she is also completely serious about it.
<<speech "Haley">>"Move up. I've been waiting since the hall."<</speech>>
<<speech "Luna">>"There's room, darling."<</speech>>
She takes him with enormous enthusiasm and absolutely no technique, and she keeps looking up to check she's doing it right, which she has never once done about anything else in her life.
<<speech "$name">>"You don't have to perform for me. Nobody's marking this either."<</speech>>
<<speech "Haley">>(pulling off, flushed and pleased) "I know. I want to be //good// at it, that's different."<</speech>>
Casey comes last and comes anyway, which is the whole of Casey. She stands at the edge of the rug for a moment with her arms folded, and then she isn't standing there, she's on her knees with the rest of them, and her face when she does it is not sarcastic at all.
<<speech "Casey">>"I'm not going to say anything about this."<</speech>>
<<speech "$name">>"Nobody's asking you to say anything. Least of all your mother."<</speech>>
<<speech "Casey">>"Good. Because I don't have anything that isn't sincere and I'd rather die."<</speech>>
<<speech "$name">>"Then don't say it. Come here instead."<</speech>>
She takes him with her eyes shut and her hand flat on his thigh, and she makes one small sound at the beginning and none after that. Luna's hand comes to rest on the back of Casey's neck at some point — the same steadying hand she'd use on Haley — and Casey lets it stay there, which is the single most extraordinary thing that has ever happened in this room.
<<else>>
The drawing room has been theirs for weeks. The dust sheets came off two rooms nobody was using and went back on nothing. The jug on the sill has the same flowers in it, dead now, and nobody has moved them.
Luna is on the chaise with her robe open and her arms out before he is through the door. Haley is on the rug at her feet with her head on her mother's knee. Casey is in the armchair with her legs already apart and no book anywhere in the room.
<<speech "Luna">>"Come here. I've had the fire lit since three."<</speech>>
<<speech "$name">>"You lit a fire in a room nobody uses and then waited by it."<</speech>>
<<speech "Luna">>"I've been waiting a great deal longer than that. Three is just when I lit the fire."<</speech>>
You take her on the chaise and she holds on with both arms and both legs and does not let go of any part of you, and she talks the whole way through it in the same quiet voice she uses for everything else.
<<speech "Luna">>"I was on my own in this house for eleven years. Eleven years, and every room of it cold."<</speech>>
<<speech "$name">>"It isn't cold now. It hasn't been cold in this house for weeks."<</speech>>
<<speech "Luna">>"No. Breed me and it never will be again. I want this house full of you."<</speech>>
She comes almost silently, the way she does everything, and holds him inside her a long moment afterwards with her heels locked at the small of his back.
Haley next, up off the rug and over the arm of the chaise before her mother has finished, laughing and completely earnest at the same time.
<<speech "Haley">>"Me. Me now. I want one that looks like you."<</speech>>
<<speech "$name">>"You've thought about it in that much detail. Of course you have."<</speech>>
<<speech "Haley">>"I've thought about the //names//. Fill me up and I'll tell you them."<</speech>>
Casey last, out of the armchair, over the back of it, gripping the upholstery with both hands, and she does not say a word until the end.
<<speech "Casey">>"Don't stop. Don't — I'll say it, I'll say it if you don't stop —"<</speech>>
<<speech "$name">>"Then say it. You've been sat on it for about a year."<</speech>>
<<speech "Casey">>"I love you. There. Breed me. That's the whole of it and I'm not repeating it."<</speech>>
Afterwards the three of them stay in the warm room, unhurried and leaking, Luna with a hand in Haley's hair and Casey sitting on the floor with her back against the armchair and her head tipped back, and all three of them looking at him with the same expression. The dead flowers stay on the sill.
<</if>>
<<case "Aria_House_Standard">>
<<if _tier is 0 or _tier is 1>>
The living room is bright and comfortable, morning light streaming through the half-open blinds, casting stripes across the worn couch. It's a Saturday, the kind of lazy morning that stretches into afternoon, and the space feels lived-in, safe, familiar.
Aria is sprawled on the couch with her legs over the armrest, her wavy dark hair falling across her face, her medium skin tone glowing in the sunlight. She wears an oversized t-shirt from some concert, her small breasts hidden beneath the fabric, her big ass pressing into the cushions. She's $name's girlfriend, has been for months, and her bright, cheerful energy fills the room like music—always up for something, always planning, always moving.
<<speech "Aria">>"Babe! You're finally here!"<</speech>> She sits up with a grin that could power a small city, her dark eyes sparkling. <<speech "Aria">>"I was starting to think you got lost on the way. Did you bring coffee? Tell me you brought coffee."<</speech>>
Anya is in the kitchen making coffee, her presence commanding even in domesticity. She's Aria's older sister, protective to the point of overbearing, and she's made her opinion of $name clear on multiple occasions. Her wavy light brown hair is pulled back in a practical ponytail, her fair skin pale against the dark cabinets, her medium breasts hidden beneath a fitted sweater. She moves with purpose, efficiency, the kind of woman who looks out for everyone whether they want it or not.
<<speech "Anya">>"He's only ten minutes late, Aria. Relax,"<</speech>> Anya says, her tone sharp but fond, protective instinct warring with genuine affection for her sister. <<speech "Anya">>"And stop calling him 'babe.' It's nauseating."<</speech>>
Ashly sits quietly in the corner armchair, still in bedwear from their sleepover—a tank top and shorts, her wavy brown hair tangled, her blue eyes soft behind a book she's not really reading. She's fair-to-medium skinned, her medium breasts rising and falling with calm breaths, her whole presence designed to fade into the background. She's Aria's shy friend, the one who notices everything but says little, the one who protects through observation rather than action.
<<speech "Ashly">>"…Hi $name,"<</speech>> She offers a small smile from behind her book, her voice barely above a whisper, her loyalty already given despite her reserve.
<<speech "Aria">>"Ignore my sister. She's been in full big-sister mode all day,"<</speech>> Aria laughs, stretching, her big ass pressing against the couch cushions. <<speech "Aria">>"So what do you want to do today? I'm up for anything! We could go out, stay in, watch movies, whatever!"<</speech>>
<<speech "Anya">>"Within reason,"<</speech>> Anya adds sharply, walking in with three mugs, her blue eyes assessing $name with the same critical evaluation she applies to everything. <<speech "Anya">>"I'm still not convinced $name is a good influence on you. But I suppose he could be worse."<</speech>>
Ashly stays quiet, but her eyes follow the interaction, her gentle observation noting everything—the way Aria lights up, the way Anya softens even while criticizing, the way $name moves through the space like he belongs there. She closes her book, sets it aside, and smiles again, small but genuine.
The morning stretches—coffee, conversation, Aria's energy filling every silence, Anya's protective commentary providing counterpoint, Ashly's quiet presence anchoring everything. It's ordinary. It's warm. It's family, chosen and given, overlapping in this sunlit living room.
<<elseif _tier is 2>>
The living room is different today. The morning light is the same, but the air is thicker, warmer, charged with something that makes the skin prickle. Aria is on the couch, but she's not sprawled anymore. She's sitting up, her legs pressed together, her oversized t-shirt hiked up to show her thighs, her dark eyes wide and wet.
<<speech "Aria">>"There you are… why does my body get so hot every time you walk in lately?"<</speech>> She fans herself, trying to sound cheerful, but her voice is breathy, her hand resting on her own knee, fingers tracing patterns. <<speech "Aria">>"I feel like I'm burning up. Like I need—something. I don't even know what."<</speech>>
Anya is in the kitchen doorway, her sweater gone, her tank top thin and clinging, her fair skin flushed, her medium breasts visible through the fabric. She's holding a coffee mug she hasn't drunk from, her hand shaking slightly, her protective nature warring with something else entirely.
<<speech "Anya">>"It's not just you. I've been feeling… off all day. Restless. Too warm,"<</speech>> She admits, crossing her arms tightly over her chest, her blue eyes locked on $name with an intensity that has nothing to do with protection. <<speech "Anya">>"I keep thinking about—no. I shouldn't. You're my sister's—"<</speech>> She stops, gasping, her hips bucking slightly against nothing, her sharp tongue silenced by physical need.
Ashly is in the corner armchair, but she's not reading. Her bedwear is damp with sweat, her tank top sticking to her medium breasts, her shorts hiked up. Her wavy brown hair is tangled, her blue eyes glazed, her thighs pressed together so tightly her hands are white-knuckled on the armrests.
<<speech "Ashly">>"…I feel weird too. Tingly. Especially when $name's close,"<</speech>> She whispers, her shy voice even softer than usual, her observation turned inward, cataloging her own arousal with the same attention she gives to everything else. <<speech "Ashly">>"I keep thinking about him touching me. About both of you touching me. About—"<</speech>> She stops, her face flushing darker, her hips rocking slightly against the chair.
<<speech "Aria">>"Ashly. You've been super quiet. You okay, girl?"<</speech>> Aria asks, but she's not really listening, her own hand having found its way between her legs, pressing through her t-shirt, her big ass lifting slightly off the couch.
<<speech "Anya">>"This isn't normal. But I can't stop looking at him,"<</speech>> Anya mutters, her protective sharpness cracking with obvious need, her hand now on her own breast, squeezing through the tank top. <<speech "Anya">>"I should be protecting Aria from you. Not— not wanting—"<</speech>>
The three of them surround you, Aria's hand finding your thigh, Anya's hand joining hers, both stroking you through your jeans, Ashly watching with glazed eyes, her hand finally moving between her own legs. The air is thick with pheromones, the living room becoming a hothouse, the family space corrupting into something else.
<<elseif _tier is 3>>
The living room has become a sanctuary of sex, the morning light turned golden and obscene, the air thick with the smell of arousal. Aria is on her knees, her oversized t-shirt gone, her small breasts exposed, her big ass presented in nothing but a thong. She's between your legs, her mouth on your cock, her dark eyes looking up with desperate devotion.
<<speech "Aria">>(pulling back, gasping, her lips swollen) "Fuck, I'm so wet just from seeing you. My pussy's been aching for hours,"<</speech>> She says, her cheerful boldness now pure sexual need. <<speech "Aria">>"Master—"<</speech>> The word escapes her, and she freezes, her face flushing, but she doesn't take it back. <<speech "Aria">>"Master, please. Let me serve you. Let me show you how much I need you."<</speech>>
Anya is beside her, her tank top ripped open, her medium breasts hanging, her fair skin marked with dark veining. Her protective nature has been completely rewritten into desperate submission, her sharp tongue now used only for begging.
<<speech "Anya">>"I hate how much I need this… but I do, Master,"<</speech>> She growls, her strong-willed personality struggling against the heat even as she obeys. <<speech "Anya">>"I'm supposed to be protecting my sister from you, not dripping for you. Not begging to suck you. But I am. Please, Master. Let me make it up to you. Let me serve."<</speech>>
She takes you from Aria, her mouth hot and desperate, her wavy light brown hair falling forward, her blue eyes looking up with devotion that terrifies her even as she feels it. Aria watches, her hand between her own legs, pumping frantically, her big ass bouncing as she fingers herself.
Ashly is in the corner, but she's not in the chair anymore. She's on the floor, her bedwear gone, her medium breasts pressed against your thigh, her shy nature completely shattered by need.
<<speech "Ashly">>"I… I can't stop thinking about you touching me, Master,"<</speech>> She whispers, her voice breaking, her observation turned to desperate participation. <<speech "Ashly">>"I used to watch. I used to notice everything. Now I just want to be noticed. Now I just want to serve. Please, Master. Let me taste. Let me please you."<</speech>>
She joins them, the three of them sharing you, passing your cock between their mouths, their faces pressed together, tongues sliding over each other, over you. Aria's cheerfulness makes her eager, sloppy. Anya's protectiveness makes her thorough, desperate to prove herself. Ashly's observation makes her skilled, attentive to every reaction.
<<speech "Aria">>(muffled, her mouth full) "Look at us, Master. My overprotective sister and my shy best friend, both soaked because of you. Both desperate to serve you. Please, Master. Please feed us. Please let us show you how good we can be."<</speech>>
<<speech "Anya">>(pulling back, gasping, her face glazed) "Master, I was wrong about you. You're exactly what we need. Please, Master. Breed us. Make us yours completely."<</speech>>
<<speech "Ashly">>(softly, her tongue learning) "Master… I've noticed everything about you. Now I just want to serve everything about you. Please, Master. Let me be useful. Let me be yours."<</speech>>
You come, spilling over their faces, their open mouths, their waiting tongues. They fight to catch it, to share it, their devotion complete, their previous relationships—sister, friend, girlfriend—transformed to collaboration in your service, all calling you Master, all completely possessed.
<<else>>
Aria's house has become a warm, pheromone-rich breeding nest. The living room is stained, the air thick, the morning light turned golden and obscene. Aria, Anya, and Ashly kneel before you completely naked, bodies marked with dark veining, pussies swollen and constantly drooling with need. Their bellies show clear signs of repeated breeding, rounded and heavy.
<<speech "Aria">>"There's my Master… I've been empty and aching all day waiting for your cum,"<</speech>> Aria says, her bright, adventurous personality now pure eager sluttiness, her small breasts hanging, her big ass presented, her dark eyes glazed with devotion. <<speech "Aria">>"Please breed me again, Master. Please fill me. I want to be pregnant with your child. I want to be your good girl, Master."<</speech>>
<<speech "Anya">>"I used to hate the idea of you with my sister… now I just want you to breed both of us, Master,"<</speech>> Anya admits, her sharp-tongued protectiveness completely broken, her medium breasts marked with your handprints, her fair skin flushed. <<speech "Anya">>"I tried to protect her from you. Now I just want to protect her place in your harem. Please, Master. Breed us both. Make us your breeding sluts, Master."<</speech>>
<<speech "Ashly">>"Please… I want to feel full again. I need you deep inside me, Master,"<</speech>> Ashly begs quietly, her shyness replaced by desperate submission, her medium breasts swaying, her wavy brown hair tangled, her blue eyes wide with devotion. <<speech "Ashly">>"I used to watch from the corner. Now I just want to be watched. Now I just want to be bred. Please, Master. Make me pregnant. Make me yours, Master."<</speech>>
<<speech "Aria">>"Look at my big sister and my shy best friend — both turned into dripping breeding whores for my Master,"<</speech>> Aria says proudly, stroking your cock, her cheerfulness channeled into sexual display. <<speech "Aria">>"Come on girls, let's drain him properly. I want all three of us pregnant at the same time, Master. I want us to be your perfect breeding harem."<</speech>>
The three girls descend on you with complete, depraved devotion—Aria's energy making her bounce, desperate to be bred; Anya's protectiveness making her hold you deep, wanting to be filled completely; Ashly's observation making her position herself perfectly, wanting to be bred most efficiently. They suck, they stroke, they present themselves, their previous relationships transformed to collaboration in your service, all calling you Master, all begging to be bred.
You take Aria first, her small breasts bouncing, her big ass presented, her body milking you desperately. She comes screaming, her cheerful energy channeled into pure sexual need. <<speech "Aria">>"Master! Master! Thank you! Thank you for breeding your good girl, Master!"<</speech>>
Anya next, her protective nature completely destroyed, her medium breasts pressed to the floor, her body convulsing as you fill her. <<speech "Anya">>"Master… thank you… for breeding your protective little slut… thank you for making me useful, Master…"<</speech>>
Ashly last, her shy nature completely silenced, her medium breasts hanging, her body shaking as you breed her. <<speech "Ashly">>"Master… I used to watch… now I just want to be watched… pregnant with your child… thank you, Master…"<</speech>>
Afterwards, the three of them lie together on the breeding floor, cum dripping from them, bellies softly rounded, faces flushed with devotion—girlfriend, sister, friend, all reduced to the same thing: warm, willing, breeding flesh, grateful to serve their Master.
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<set $sceneColor = "#cc66ff">>
<<set $sceneLabel = "Mall · Retail">>
<div class="location-scene-wrap" style="padding:0 20px 32px;">
<<include "LocationScene-Header">>
<div class="narrative-box">
<<switch _id>>
<<case "Clothing_Store_Standard">>
<<if _tier is 0 or _tier is 1>>
Melissa is $name's godmother and has never treated that as an honorary position. She helped raise him and Elsa and Jewelz after their parents died, alongside her own daughter, and the practical expression of it these days is that she turns up unannounced and takes him shopping.
Which is what has happened. The boutique is at the bright end of the mall, everything arranged by colour, a steamer hissing behind the fitting rooms and a playlist trying very hard. Melissa works the racks with the certainty of a woman who decided what she was buying before she left the house — shoulder-length brown hair going lighter at the ends, sleeves pushed up, hazel eyes narrowing at a collar.
<<speech "Melissa">>"Arms out."<</speech>>
<<speech "$name">>"I have clothes. I'm wearing clothes right now, you're looking at them."<</speech>>
<<speech "Melissa">>"You have one hoodie and a coat you've had since school. Arms out."<</speech>>
Vina is here because Vina is usually somewhere near her mother. She's petite and dark-haired and easy about everything, and she and $name grew up in and out of the same kitchen without ever quite becoming close — these days they cross paths rather than meet, and it's never awkward. She has the armchair by the fitting rooms and is holding the rejects.
<<speech "Vina">>"She's been at this since breakfast. She had it planned."<</speech>>
<<speech "$name">>"Planned to what extent? Should I be worried about the scale of this?"<</speech>>
<<speech "Vina">>"Far enough that she knows your size and I don't want to think about how."<</speech>>
<<speech "Melissa">>"I bought you school shirts for six years. It isn't witchcraft."<</speech>>
The assistant manager has been watching the pile grow with professional interest. Skylar is tall and platinum-blonde and knows this stock better than the owner does, and she's been saving to study fashion properly for as long as she's worked here — which shows in the way she looks at a garment before she looks at the person holding it.
<<speech "Skylar">>"Not that one."<</speech>>
She takes it out of Melissa's hand, turns the collar out, shows her something in the seam and hands it back.
<<speech "Skylar">>"It's cut for a shorter neck. He'll wear it once, hate it, and never say why."<</speech>>
<<speech "Melissa">>"//Thank you.// Someone who looks at the garment."<</speech>>
<<speech "$name">>"You're supposed to be selling us clothes, not talking us out of them."<</speech>>
<<speech "Skylar">>(already moving to the next rail) "I'm selling you the one you'll come back for."<</speech>>
The fitting is genuine and takes a while. Melissa sends him into the cubicle and comes to the curtain, adjusting a shoulder seam with two fingers, turning him by the elbow to see it in better light. Vina passes garments over the door. Skylar produces a tape measure and takes a real measurement across his back.
Then Melissa finds a jacket, and stops, and doesn't say anything for a moment.
<<speech "Melissa">>"Put it on."<</speech>>
<<speech "$name">>"I know what that costs, it's written on the sleeve."<</speech>>
<<speech "Melissa">>"And I know what I earn, and we're not having that conversation standing in a shop."<</speech>>
He puts it on. She smooths the shoulders down with both hands and looks at him in the mirror, and her face does something she doesn't bother hiding.
<<speech "Melissa">>"There. That's what you look like."<</speech>>
<<speech "Vina">>(from the armchair, fond and embarrassed) "Mum."<</speech>>
<<speech "Melissa">>"I'm allowed. I've known him since he was small enough to lose in a supermarket."<</speech>>
Skylar rings it through, does something at the till that takes longer than it should, and the figure on the display is not the figure on the sleeve. Nobody remarks on it. Melissa puts a hand flat on the counter on the way past, and that is the whole of the thanks, and Skylar seems satisfied.
<<elseif _tier is 2>>
The shop is open and mildly busy the way it always is. Two women are working through the sale rail, somebody's child is under a display table, the playlist is the same playlist. The air has gone warm and thick and sweet, and none of them has said a word about it.
Melissa is doing the fitting again, properly — him out of the jacket and back into it, hands working real seams, tugging a cuff straight. Then the hands simply stay, and she leans her forehead between his shoulder blades and carries on talking to him in the mirror.
<<speech "Melissa">>"That shoulder still isn't sitting right. It's the way you stand."<</speech>>
<<speech "$name">>"You've been telling me that since I was at school and I've never once fixed it."<</speech>>
<<speech "Melissa">>"Because you've been standing like that since you were fourteen, sweetheart."<</speech>>
Her arms come the rest of the way round him. A woman at the sale rail glances over, sees a woman with her arms round a young man in the middle of a shop, and goes back to the sale rail.
Vina has stopped holding the rejects. She's holding his hand instead, both of hers round it, not doing anything with it — she has simply taken it and kept it, and she's watching the side of his face rather than the rails.
<<speech "Vina">>"I think about you at completely useless moments. Putting the bins out. It's nice. I don't want anything from it."<</speech>>
<<speech "$name">>"You have never once said anything like that to me. Not in twenty years of kitchens."<</speech>>
<<speech "Vina">>"No. It's been true for a while though."<</speech>>
She goes pink and doesn't let go.
Skylar comes over with a folded jumper she has no reason to be carrying, sets it down where it doesn't belong, and steps in against him. His hand goes inside her blouse and she leans into it and shuts her eyes, and her breath goes uneven, and she keeps talking in exactly the voice she'd use to describe a return policy.
<<speech "Skylar">>"I keep imagining my own shop. And you're in it, which is ridiculous, because you'd be bored senseless in a shop."<</speech>>
One of the women from the sale rail comes over with a blouse and a question about sizes. Skylar answers her without moving away from him and without taking his hand out of her blouse, gives her the right answer, points her at the right rail, and thanks her.
<<speech "$name">>"You served her. My hand was inside your blouse and you served her."<</speech>>
<<speech "Skylar">>"She needed a fourteen. It's not a hard question."<</speech>>
Melissa's grip goes tight across his ribs. It takes her all at once — her breath catches, her whole body locks against his back, and for a few seconds she is somewhere else entirely with her face pressed into him. Then it passes and she laughs at herself, a bit unsteady, and picks the tape measure up off the floor where she has dropped it without noticing.
<<speech "Melissa">>"…Sorry, love. What was I telling you?"<</speech>>
<<speech "$name">>"That I stand wrong, and that you've given up trying to fix it."<</speech>>
<<speech "Melissa">>"Well. You do."<</speech>>
<<elseif _tier is 3>>
The fitting room corridor has a bench along one wall and a mirror at the end that flatters everybody. The shop is open. Skylar has not turned the sign round and it hasn't occurred to any of them that she might.
Vina goes down first, on her knees on the corridor floor, and rests her forehead against his stomach for a second before she does anything else.
<<speech "Vina">>"Don't look at me for a minute."<</speech>>
<<speech "$name">>"Why not? You've never minded being looked at before."<</speech>>
<<speech "Vina">>"Because I'll laugh, and I don't want to laugh, I want to do this properly."<</speech>>
She takes him in her mouth carefully and slowly, both hands flat on his thighs, and after a moment she does look up after all, checking his face, and whatever she finds there makes her make a small pleased sound around him.
Melissa lowers herself onto the bench beside her and puts a hand on the back of Vina's neck, warm and steady, the same hand that has been steadying that neck since Vina was small enough to need it.
<<speech "Melissa">>"Slowly. He isn't going anywhere, love."<</speech>>
<<speech "$name">>"You realise you're talking your daughter through it."<</speech>>
<<speech "Melissa">>"I'm helping. I'm not explaining myself with my mouth full."<</speech>>
She takes over, and she isn't slow at all. There is something almost devotional in it — unhurried, total, her eyes coming up to his the way they used to across a kitchen table when she was checking he'd eaten.
<<speech "Melissa">>"You're such a good boy. You always were, even when you weren't."<</speech>>
<<speech "$name">>"You used to say that when I'd broken something."<</speech>>
<<speech "Melissa">>(comfortably) "You'd broken a great many things. It was true then as well."<</speech>>
Skylar arrives last because Skylar finishes what she's doing first. She still has the till key in her hand, notices, and puts it in her pocket rather than leaving it anywhere it could go missing.
<<speech "Skylar">>"Move up."<</speech>>
<<speech "Vina">>"There's room."<</speech>>
<<speech "Skylar">>"Not the way you're kneeling there isn't."<</speech>>
She kneels and takes him with the same unbothered competence she brings to a stock count, and it is startling how much care is underneath it. Out on the floor the door goes and someone walks the sale rail and out again without being served, and not one of them turns her head.
<<speech "$name">>"Somebody just walked the whole length of your shop and left again."<</speech>>
<<speech "Skylar">>(off him, entirely level) "They'll come back on Saturday. They always do."<</speech>>
<<else>>
The corridor is where it happens now and there is nothing hurried or hidden about any of it. The lights are on, the door is unlocked, and a delivery has been sitting behind the counter for days that nobody has opened.
Melissa is on the bench with her skirt gone and her arms already out. Vina is on the floor at her feet with her head resting against her mother's knee, waiting, unbothered about waiting. Skylar is standing half out of her blouse, heavy and flushed and perfectly calm about it.
<<speech "Melissa">>"Come here to me."<</speech>>
<<speech "$name">>"You've been waiting for this since the jacket. Probably before the jacket."<</speech>>
<<speech "Melissa">>"Since well before the jacket. It's the nicest part of my week."<</speech>>
You take her on the bench and she wraps herself round you with her whole body and doesn't stop talking, and what she says is worse than anything the other two could manage because of how gently she says it.
<<speech "Melissa">>"That's it. That's my boy. Give it to me properly — I want to be carrying it."<</speech>>
<<speech "$name">>"Everybody would know. The whole town would know inside a week."<</speech>>
<<speech "Melissa">>"I'd tell them at the door. I'd be so pleased I'd tell them before they asked."<</speech>>
She comes with her mouth against his neck saying his name, and afterwards she keeps her legs locked around him a long moment on purpose, smiling with her eyes shut, holding it in.
Vina next, up on the bench beside her mother, holding his face in both small hands the entire time.
<<speech "Vina">>"Look at me while you do it. I want to see it happen."<</speech>>
<<speech "$name">>"I'm looking at you. I haven't looked anywhere else."<</speech>>
<<speech "Vina">>"Then fill me up. All of it. I want it to take."<</speech>>
Skylar last, bent over the bench, reaching back to guide him in herself, and she talks shop the whole way through because it genuinely does not occur to her to stop.
<<speech "Skylar">>"Tuesdays and Thursdays are quiet. Afternoons especially."<</speech>>
<<speech "$name">>"You've worked out when it's convenient to get bred."<</speech>>
<<speech "Skylar">>"I work out when everything happens. Breed me on a Tuesday and I'll still open on time."<</speech>>
Afterwards the three of them stay where they are, unhurried, leaking onto the bench and the corridor floor — Melissa with a hand in Vina's hair, Vina's head in her lap, Skylar sitting on the step with her blouse hanging open — all three looking at him with the same expression. Out on the floor the door goes and somebody walks the sale rail and leaves again.
<</if>>
<<case "Electronics_Standard">>
<<if _tier is 0 or _tier is 1>>
The electronics shop is the second unit from the escalator and lit like an operating theatre. Eight televisions on the back wall play the same drone footage of a coastline, slightly out of sync, so the same wave breaks eight times in a row.
Kate is on the phone and losing. She has it wedged against her shoulder and both hands inside a customer's camera — back plate off, ribbon cable lifted, the battery door in a little dish beside her like a tooth. Every thirty seconds she says //yes// in a tone that gets flatter.
<<speech "Kate">>(into the phone) "I know what the serial says. I'm looking at the serial. The serial and the sticker inside the door don't match, which is what I rang about."<</speech>>
She puts the spudger down, holds the battery door under the lamp, and puts it back.
Down the far end Demi has turned the lens cabinet into a photo bench — white card against the wall, a desk lamp on a box, a second lamp stolen from elsewhere in the shop. She is shooting product photos for the listing page because Kate asked her weeks ago.
<<speech "Demi">>"Hold that. No — up. Up and towards me, you're bouncing it into the ceiling."<</speech>>
$name is holding a reflector, which is a bent piece of foil-covered card, and has been for about four minutes.
<<speech "$name">>"You said ten minutes. That was at four, and I've got a dead arm and a piece of card."<</speech>>
<<speech "Demi">>"It would have taken ten minutes if the shop lights weren't green. Look at the card. That's green. Everything in here is faintly green and nobody but me has ever noticed."<</speech>>
She takes three frames, checks the back of the camera, moves the box two inches, takes three more. She is quiet in shops the way she is quiet everywhere, right up until she has something she cares about, and then she talks continuously and doesn't notice.
<<speech "Demi">>"Left hand down an inch."<</speech>>
<<speech "$name">>"You could put this on a stand and we could both go home."<</speech>>
<<speech "Demi">>"A stand doesn't have wrists. Down an inch."<</speech>>
Kate finishes the call by saying //fine// twice and not saying goodbye, and sets the phone face down with enough control that it's obviously deliberate.
<<speech "$name">>"That went well. Was that the fifth call or the sixth?"<</speech>>
<<speech "Kate">>"They'll cover the sensor and not the shutter. The shutter is the thing that's broken."<</speech>>
She starts putting the camera back together fast and neatly, which is the only place her temper shows.
<<speech "Kate">>"He's had it four years. He comes in tomorrow and I have to say a number to him."<</speech>>
<<speech "Demi">>"How big a number?"<</speech>>
<<speech "Kate">>"Bigger than the camera's worth. That's always the number."<</speech>>
Two customers are in — a man comparing soundbars by picking them both up, which tells him nothing, and a woman in the doorway saying into her phone that she'll send a picture.
Demi lowers the camera and looks at the back of it a long moment.
<<speech "Demi">>"That's the one. That's the shot, we can stop."<</speech>>
She brings it over at completely the wrong angle, so $name has to take her wrist and turn it.
<<speech "$name">>"It's a lens. On a box. I held a piece of card for forty minutes."<</speech>>
<<speech "Demi">>"It's a lens on a box //that looks like it's worth buying//. That's the whole job. That's forty minutes of my life and I'd like some acknowledgement."<</speech>>
<<speech "Kate">>(not looking up from the reassembly) "It's good, Demi."<</speech>>
<<speech "Demi">>"Thank you. That's all I wanted."<</speech>>
She starts dismantling the lights and does not put a single one back where it came from.
<<elseif _tier is 2>>
The shop is open and the eight televisions are still working through the same coastline. The air has gone thick and sweet and close, and it has been building for twenty minutes.
The camera is still in pieces. That's the first thing. Kate had the back plate off and the ribbon lifted and at some point simply stopped, and the spudger lies across the open body where it will get knocked.
She is at the end of the counter instead, both palms flat on the glass, leaning, watching the doorway he came through.
<<speech "Kate">>"You were gone a long time."<</speech>>
<<speech "$name">>"There's an open camera on your counter and you're watching the door."<</speech>>
<<speech "Kate">>"I know. I know how that sounds. Come round this side."<</speech>>
He does. She gets a hand into his belt before he's fully behind the counter, and when he takes hold of her she makes a sound and her hip knocks the little dish and the battery door goes onto the floor and neither of them looks at it.
Demi still has the lights out. She is at the photo bench with the reflector in one hand, and she has been standing very still for a while — long enough that the desk lamp has started to smell faintly of hot dust.
<<speech "Demi">>"Can you come here."<</speech>>
<<speech "$name">>"You've got a shot to finish."<</speech>>
<<speech "Demi">>"I've taken the shot. I took the shot twenty minutes ago and I've been standing here holding a piece of card."<</speech>>
She looks at the reflector like she's only just found it in her hand, and then puts it down on the box, badly, and it slides off.
<<speech "Demi">>"So I'm going to say something and I want it on the record that I know exactly how it sounds."<</speech>>
<<speech "$name">>"Go on."<</speech>>
<<speech "Demi">>"I have a whole personality built on not being the person who says this."<</speech>>
She crosses the shop, takes his hand, and puts it where she wants it, and then her legs go and she has to catch the edge of the lens cabinet with her free arm. The cabinet is full of glass. She doesn't notice that either.
<<speech "Demi">>"That. Don't stop doing that."<</speech>>
<<speech "$name">>"Then stand up properly. You've got hold of two thousand pounds of stock."<</speech>>
<<speech "Demi">>"I'm working on it."<</speech>>
Kate makes a small frustrated noise from behind the counter, because his other hand has gone and she has noticed.
<<speech "Kate">>"Both of us. You can do both of us, you've got —"<</speech>>
She stops mid-word. Her hand closes white on the counter edge, her head goes back, her hips roll once, and for four seconds she is not present in the shop in any meaningful way. Then she comes back, blinking, and looks down at the open camera as though she cannot work out how it got that way.
<<speech "Kate">>"…What was I asking for?"<</speech>>
<<speech "$name">>"Both of you. You'd got as far as the arithmetic."<</speech>>
<<speech "Kate">>"Right. Yes."<</speech>>
The woman in the doorway says she'll send a picture, and doesn't, and leaves. The battery door stays on the floor.
<<elseif _tier is 3>>
The stockroom is behind a strip curtain, and it is not private. There is no door. The counter is nine feet away and the bell on the shop door still works.
Kate goes through first and is on her knees before he's fully through the curtain, and she doesn't say anything at all for the first few seconds, which for Kate is the loudest thing she could do. When she does speak it comes out in pieces between what she's doing.
<<speech "Kate">>"Every time. Every single time you come in and I have to stand there and //ring things through// —"<</speech>>
<<speech "$name">>"Nobody's stopping you. You've got about ninety seconds before that bell goes."<</speech>>
She takes that as an instruction and stops talking.
Demi comes through the curtain sideways, already unbuttoned, and drops onto her knees next to Kate hard enough that it must genuinely hurt. She doesn't react to it.
<<speech "Demi">>"Move over. I've been out there on my own holding a light, that's —"<</speech>>
<<speech "$name">>"Then don't waste it explaining."<</speech>>
<<speech "Demi">>"No. Right. Yes."<</speech>>
She takes him from the other side and immediately makes the noise she has spent her entire life not making in public, and then makes it again. Kate laughs at her and the laugh turns into a groan halfway through, and the two of them work at him with no coordination whatsoever, bumping shoulders, getting in each other's way, neither willing to yield an inch of it.
<<speech "Demi">>(surfacing, wrecked) "This is so far below my standards. I want you to know I //know// that."<</speech>>
<<speech "$name">>"Noted, and forgotten. Stop talking and open your mouth."<</speech>>
<<speech "Demi">>"Yeah. Okay."<</speech>>
The bell on the shop door goes. Somebody walks the length of the shop, stands at the counter for a moment beside an open camera in pieces, and walks out again. Neither of them stops. Kate's hand finds Demi's on his thigh and grips it hard, and they take him in turns until his fist closes in Kate's hair.
<<speech "Kate">>(hoarse, hands already reaching) "Me. Please. I've been asking for two hours, please —"<</speech>>
<<speech "$name">>"You'll get it. Neither of you is going back out on that floor yet."<</speech>>
<<else>>
The strip curtain is tied back now, because nobody bothers with it any more. The shop is open. The eight televisions are still breaking the same wave eight times out on the wall, and the stockroom smells of it, and the camera on the counter has been in pieces for days.
Kate is over the box shelving with her top gone and her jeans round one ankle, already soaked to the thigh, pushing back before he has touched her. Demi is on the floor with her back against the racking and her legs open and both hands working and her eyes fixed on him.
<<speech "Kate">>"Please. Please, I've been —"<</speech>>
<<speech "$name">>"Say it properly. You've had all day to work out the wording."<</speech>>
<<speech "Kate">>"Put it in me. Please put it in me, I'll do the whole shift like this, I don't care —"<</speech>>
You take her and she goes off almost immediately, hard, loud enough that it carries out onto the floor, and she does not stop asking through any of it.
<<speech "Kate">>"Don't pull out — I want it in me, I want to be full of it when I'm out there serving —"<</speech>>
<<speech "$name">>"You'll be standing at that counter in ten minutes."<</speech>>
<<speech "Kate">>"//I know.// Breed me anyway. I'll stand there and smile and drip and nobody will know."<</speech>>
Demi is up on her knees and has stopped pretending to have any dignity left in the matter at all.
<<speech "Demi">>"Me next. Please. I'm not proud, I've got nothing left to be proud with —"<</speech>>
<<speech "$name">>"Come here then. Over the shelving, same as her."<</speech>>
<<speech "Demi">>"Thank you. God. Thank you."<</speech>>
She takes it face down with her fingers hooked into the mesh, and she talks the whole way through it, the sarcasm gone somewhere she can't reach it, everything narrowed down to asking for the same thing again and again.
<<speech "Demi">>"Deeper — please — I want it to take, I want to walk home like this and sit down at the table —"<</speech>>
When you finish in her she stays there with her forehead on her forearm, shaking, leaking down the inside of her thigh, and asks once more anyway on the off chance.
<<speech "Demi">>"…Again?"<</speech>>
<<speech "$name">>"Give it a minute. You can't stand up yet."<</speech>>
Out on the floor the bell goes and somebody starts comparing the two soundbars by picking them both up, which tells him nothing.
<</if>>
<<case "Dept_Store_Standard">>
<<if _tier is 0 or _tier is 1>>
The department store is a maze of bright lights and polished floors, the air thick with the scent of perfume and new fabric. Kali leans against a display of scarves, her fingers idly tracing the patterns as she hums along to the music playing through her earbuds. Her cropped band tee rides up slightly, revealing a sliver of toned stomach, and her ripped jeans hug her hips in a way that’s distracting. Jewelz stands nearby, arms crossed, her sharp blue eyes scanning the sales racks with the precision of someone used to budgeting. Her leather jacket is slung over her shoulder, her tank top clinging to her curves.
$name trails behind them, his hands shoved in his pockets. The parasite stirs—just a little—but he ignores it. For now.
Kali spots him first and grins, pulling out her earbuds. <<speech "Kali">>"Well, well, if it isn’t little $name all grown up and brooding in the women’s section."<</speech>> She nudges Jewelz with her elbow. <<speech "Kali">>"You think he’s here to buy something for Aria, or is he finally admitting he’s got a type?"<</speech>>
Jewelz snorts, her lips quirking. <<speech "Jewelz">>"Please. If he had a type, he’d know exactly what he likes by now."<</speech>> She steps closer, her hip bumping into his. <<speech "Jewelz">>"So which is it, baby $familymale? You lost, or you planning something?"<</speech>>
$name rolls his eyes, but there’s no real heat in it. Only with Kali can Jewelz relax and act like a normal girl, not just a young girl forced to grow up too quickly. <<speech "$name">>"I’m here because you dragged me here. Remember? ‘$name, we need new clothes. $name, you have terrible taste. $name, help us carry stuff.’"<</speech>>
Kali laughs, tossing a scarf at his face. <<speech "Kali">>"Oh, boo-hoo, the big strong guy has to carry bags for his $family and the hot friend. Poor baby."<</speech>> She saunters closer, her fingers trailing over the fabrics on display. <<speech "Kali">>"Besides, you know you love it. Admit it—you miss us when we’re not around."<</speech>>
Jewelz smirks, her hand landing on his shoulder—possessive, teasing. <<speech "Jewelz">>"He does get all twitchy when we’re not there to keep an eye on him."<</speech>> Her thumb brushes over his collarbone, just for a second. <<speech "Jewelz">>"Almost like he needs us."<</speech>>
$name exhales sharply, but the parasite purrs, his skin tingling where they touch him. <<speech "$name">>"I need you like I need a hole in the head."<</speech>>
Kali waggles her eyebrows. <<speech "Kali">>"Oh, so you do think about holes—"<</speech>>
Jewelz laughs, the sound rich and warm. <<speech "Jewelz">>"Kali, stop."<</speech>> But she doesn’t move her hand. Instead, her fingers tighten just slightly. <<speech "Jewelz">>"C’mon, help us pick out something nice. Elsa’s birthday is coming up, and you know she’ll kill us if we don’t get her something good."<</speech>>
$name should pull away. But he doesn’t.
The parasite stretches, its tendrils coiling around his spine.
<<speech "$name">>"Fine. But if I have to carry all the bags, I’m charging you."<</speech>>
Kali grins, linking her arm through his. <<speech "Kali">>"Deal. But only if you promise to be nice."<</speech>> Her fingers trace idle patterns on his wrist.
Jewelz’s smirk deepens. <<speech "Jewelz">>"Oh, we’ll make sure you’re very nice."<</speech>>
<<elseif _tier is 2>>
The parasite thrums in $name’s chest, its influence seeping into his veins like liquid heat. The department store feels different—the lights softer, the air thicker, the scent of Kali’s vanilla perfume and Jewelz’s leather jacket intoxicating. Kali’s cropped top rides higher now, her jeans tighter, her fingers twitching like she’s fighting the urge to touch herself. Jewelz’s jacket is unzipped, her tank top clinging to her sweat-slicked skin, her nipples hard beneath the fabric.
Kali spots him first and grins, her teeth sinking into her lower lip. <<speech "Kali">>"Well, look at you. All mysterious and smoldering in the lingerie section."<</speech>> Her voice is softer, warmer. She steps closer, her hip brushing against his. <<speech "Kali">>"You planning on buying something special, or are you just admiring the view?"<</speech>>
Jewelz’s gaze lingers on him, her usual sharpness dulled by something hungrier. <<speech "Jewelz">>"He’s definitely admiring something."<</speech>> Her hand lands on his chest, her fingers spreading over his heartbeat. <<speech "Jewelz">>"Aren’t you, baby $familymale?"<</speech>>
$name doesn’t pull away. The parasite whispers: They’re yours. Take them.
<<speech "$name">>"Depends."<</speech>> His voice is deeper, rougher. His hand slides around Kali’s waist, pulling her flush against him. <<speech "$name">>"On whether you two can behave."<</speech>>
Kali gasps, her back arching slightly. <<speech "Kali">>"Oh, behaving is overrated."<</speech>> Her fingers dig into his shoulders, her nails scoring through his shirt. <<speech "Kali">>"Besides, I like it when you’re bad."<</speech>>
Jewelz’s lips curl. <<speech "Jewelz">>"Mmm. Me too."<</speech>> Her hand slides down, her fingers brushing over the front of his jeans. <<speech "Jewelz">>"But I know you can be good when you want to be."<</speech>> Her thumb traces the outline of his cock, already hard beneath the fabric.
$name’s breath hitches. The parasite purrs.
<<speech "$name">>"Who said I wanted to be good?"<</speech>>
Kali moans, her hand slipping under his shirt, her nails dragging down his back. <<speech "Kali">>"Fuck, $name…"<</speech>> Her voice is a whimper.
Jewelz’s fingers tighten around his cock, squeezing through the denim. <<speech "Jewelz">>"Then don’t."<</speech>> Her voice is a growl, her free hand gripping his hip. <<speech "Jewelz">>"Show us how bad you can be."<</speech>>
$name pushes Kali against the nearest display, his mouth crashing onto hers. She melts into him, her legs wrapping around his waist as he grinds against her. Jewelz watches, her hand working her own jeans open, her fingers slipping inside.
<<speech "Jewelz">>"That’s it… teach her a lesson... right here."<</speech>> Her voice is rough, her breath hitching as she touches herself. <<speech "Jewelz">>"Let me watch."<</speech>>
Kali breaks the kiss, her lips swollen, her eyes glazed. <<speech "Kali">>"Y-Yes… please…"<</speech>>
<<elseif _tier is 3>>
Kali is on her knees in front of $name before he even fully steps into the aisle, her lips parted, her hands fumbling with his belt. Her cropped top is gone, her bra pushed up to frame her tits, her jeans unbuttoned and sliding down her thighs. Jewelz leans against a display, her jacket pooling on the floor, her tank top ripped open, her fingers buried inside her panties as she watches.
<<speech "Kali">>"N-$name…"<</speech>> Kali breathes, her voice a moan. Her tongue darts out, swirling over the head of his cock as she frees it. <<speech "Kali">>"I’ve been thinking about this…"<</speech>> Her hands grip his thighs, her nails digging in. <<speech "Kali">>"About how good you’d taste…"<</speech>>
Jewelz whimpers, her fingers working faster inside herself. <<speech "Jewelz">>"Fuck, Kali…"<</speech>> Her free hand grips her own breast, her thumb rolling over her nipple. <<speech "Jewelz">>"Let me help."<</speech>> She crawls forward, her mouth joining Kali’s as they worship his cock together.
$name groans, his hands tangling in their hair. <<speech "$name">>"That’s it… good girls…"<</speech>> His hips jerk forward, his cock hitting the back of Kali’s throat. She gags, but her hands only tighten on his ass, pulling him deeper.
Jewelz takes over, her mouth stretching around him as she takes him to the root. <<speech "Jewelz">>"Mmm—fuck, you’re huge…"<</speech>> She pulls back, her lips popping off the head. <<speech "Jewelz">>"I knew you’d be perfect."<</speech>> Her tongue swirls over the tip before she dives back in, her throat fluttering around him.
Kali moans, her hand slipping between her thighs, her fingers circling her clit. <<speech "Kali">>"Y-You taste so good…"<</speech>> Her voice is a sob, her free hand groping at her own breast.
Jewelz pulls back, her lips glistening. <<speech "Jewelz">>"C’mon, Kali. Share."<</speech>> She grins, her hand wrapping around the base of his cock as she guides Kali’s mouth back to him.
Kali obeys, her tongue swirling over the head before she takes him deep, her throat convulsing around him. Jewelz watches, her fingers furious inside herself.
<<speech "Jewelz">>"That’s it… choke on him."<</speech>> Her voice is a growl, her breath hitching. <<speech "Jewelz">>"He loves it when you gag."<</speech>>
<<else>>
The department store isn’t a store anymore. It’s a breeding ground, the air thick with the scent of sex and submission, the floors slick with sweat and arousal. The parasite has rewritten them—mind, body, soul.
Kali is naked, her body marked with the parasite’s creeping veins, her tits swollen, her cunt dripping onto the floor. Jewelz is bent over a display table, her ass in the air, her pussy clenching around nothing, her moans slurred and desperate.
<<speech "Kali">>"N-$name…"<</speech>> Kali whines, crawling toward him, her nails scoring the polished floor. <<speech "Kali">>"We were supposed to be shopping…"<</speech>> She giggles, the sound broken, her mouth drooling in anticipation.
Jewelz sobs, her hips rocking back, her ass jiggling. <<speech "Jewelz">>"P-Please… I c-can’t think anymore…"<</speech>> Her voice is guttural, her usual dominance gone. <<speech "Jewelz">>"Just fuck me… Breed me…"<</speech>>
$name grins—or rather, the parasite grins through him.
He slams into Jewelz first, her tight cunt swallowing him whole as she screams, her nails scoring the table. Kali crawls under him, her tongue dragging up his balls before she licks where he’s stretching Jewelz open.
<<speech "Kali">>"Yes—! Ruin her—! Ruin us all—!"<</speech>> Kali moans, her tongue swirling over Jewelz’s clit as $name pounds into her.
Jewelz’s words dissolve into gibberish, her body convulsing as she comes, her cunt milking him. <<speech "Jewelz">>"N-$name—! Fuck—! MORE—!"<</speech>>
Kali whimpers, her fingers furious inside herself as she watches, her other hand pinching her nipple hard. <<speech "Kali">>"I-I love you two…"<</speech>> Her voice is a sob, her mind gone. <<speech "Kali">>"I love you two so much—!"<</speech>>
$name pulls out of Jewelz, her cunt gaping as his cum spills out of her. He grips Kali by the hips, flipping her onto the display table, her ass slapping against the glass as he slams into her. Jewelz crawls up, her mouth finding his, her tongue forcing its way in as she rides his thigh, her cunt grinding against him.
<<speech "Jewelz">>"Breed us…"<</speech>> Jewelz pants against his lips. <<speech "Jewelz">>"Make us yours…"<</speech>>
Kali screams, her back arching as her own orgasm hits, her juices spilling over his cock. <<speech "Kali">>"I-I need you forever—! PLEASE—!"<</speech>>
The parasite roars in triumph.
Good. Now fill them all.
<<speech "$name">>"Time for another round."<</speech>> His voice is not his own.
The parasite laughs.
<<speech "Kali">>"Y-Yes… please…"<</speech>> Kali sob, her legs spreading wider.
<<speech "Jewelz">>"Always…"<</speech>> Jewelz growls, her nails digging into his skin.
The parasite sings as their minds shatter, their bodies convulsing in unison.
<</if>>
<</switch>>
</div>
<<include "LocationScene-Footer">>
</div><<nobr>>
<<set _loc = $sceneLocation>>
<<set _id = $activeSceneID>>
<<set _tier = $sceneTier>>
<<set _color = $sceneColor || "#44ff88">>
<<set _label = $sceneLabel || "Scene">>
<</nobr>>
<div @style="'border-bottom:2px solid ' + _color + '; padding-bottom:12px; margin-bottom:20px; text-align:center;'">
<div style="font-size:0.75em; color:#555; text-transform:uppercase; letter-spacing:0.12em; margin-bottom:4px;">
<<print _label>> (Tier <<print _tier>>)
</div>
<h1 @style="'margin:0; color:' + _color + '; font-size:1.6em;'"><<print _loc>></h1>
</div>
/* ── PORTRAITS ── */
<<if $sceneGroup and $sceneGroup.length > 0>>
<div style="display:flex; gap:12px; justify-content:center; align-items:flex-end; margin-bottom:24px; flex-wrap:wrap;">
<<for _pgid range $sceneGroup>>
<<set _pgc = State.variables[_pgid]>>
<<if _pgc and _pgc.met>>
<<capture _pgid>>
<div style="text-align:center; flex:1; min-width:100px; max-width:200px;">
<img @src="window.getTierImagePath(_pgc.name, _tier)"
@data-fallback="window.getEventImagePath(_pgc.name)"
onerror="if(!this.dataset.tried){this.dataset.tried=1;this.src=this.dataset.fallback;}"
style="width:100%; border-radius:8px; border:2px solid #bd59ff; display:block;">
<div style="color:#bd59ff; font-size:0.88em; margin-top:6px; font-weight:bold;"><<print _pgc.name>></div>
<div style="color:#555; font-size:0.75em; margin-top:2px;">Corr: <<print _pgc.corr>>%</div>
</div>
<</capture>>
<</if>>
<</for>>
</div>
<</if>>
<div style="text-align:center; margin-top:24px;">
<<button "Continue">>
<<set $activeSceneID = null>>
<<set $sceneLocation = null>>
<<set $sceneTier = null>>
<<set $sceneGroup = []>>
<<set $sceneColor = null>>
<<set $sceneLabel = null>>
<<goto "TownHub">>
<</button>>
</div>
/* Explicit destination rather than a back macro. `back` REWINDS the variable
state to before this passage was entered instead of navigating, so anything
done here is discarded -- and with no history it cannot resolve at all. */
[[← Back to the Hub|TownHub]]
<div style="max-width:820px; margin:0 auto; padding:6px;">
<div style="text-align:center; margin-bottom:20px;">
<h1 style="color:#bd59ff; margin-bottom:4px;">☣ How This Works</h1>
<div style="color:#555; font-size:0.85em; font-style:italic;">Click any section to expand it.</div>
<div style="color:#555; font-size:0.8em; margin-top:6px;">Every number here is the real one, read from the game's own code.</div>
</div>
/* ═══════ 1. THE BASICS ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ The Basics — start here
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<p>You are <b style="color:#ccc;">$name</b>, and something is living inside you. It wants to spread.</p>
<p>Every day you visit locations, meet girls, and use <b style="color:#bd59ff;">parasites</b> to infect and corrupt them. Each night the world moves on its own — girls travel, corruption deepens, and the authorities take notice.</p>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; padding:8px 12px; margin:10px 0;">
<b style="color:#bd59ff;">The loop:</b> Wake → travel & act → sleep → night report → repeat.
</div>
<p><b style="color:#ccc;">Parasites</b> are your currency. They pay for infections, nests and upgrades.</p>
<p><b style="color:#ccc;">Four ways to get them:</b></p>
<ul style="margin:6px 0 12px 18px; line-height:1.8;">
<li><b style="color:#bd59ff;">Produce Parasite</b> — the button in the side menu, or press <b>P</b>. Costs you the whole day, but it always works. This is your fallback when you have nothing better to do.</li>
<li><b style="color:#ccc;">Breeding nests</b> — +1 every night for as long as the nest survives</li>
<li><b style="color:#ccc;">Bred girls</b> — a girl at corruption 75+ who has already been bred gives +2 when she visits you in the morning</li>
<li><b style="color:#ccc;">Goals</b> — the largest single payouts</li>
</ul>
<p><b style="color:#ccc;">Time</b> only advances when you sleep. Wandering is free — but each <i>action</i> can raise suspicion.</p>
</div>
</details>
/* ═══════ 2. CORRUPTION ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ Corruption & the Cap
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<p>Every girl has a <b style="color:#cc88ff;">corruption</b> score from 0 to 100. It rises each night once she is infected, at a rate set by your <b>Infection Power</b>.</p>
<table style="width:100%; border-collapse:collapse; margin:10px 0; font-size:0.92em;">
<tr><td style="padding:4px 8px; color:#666;">0</td><td style="padding:4px 8px;"><b>Unaware</b> — she has no idea</td></tr>
<tr><td style="padding:4px 8px; color:#8888cc;">25</td><td style="padding:4px 8px;"><b style="color:#8888cc;">Curious</b> — drawn to you, doesn't know why</td></tr>
<tr><td style="padding:4px 8px; color:#bd59ff;">50</td><td style="padding:4px 8px;"><b style="color:#bd59ff;">Receptive</b> — inhibitions gone</td></tr>
<tr><td style="padding:4px 8px; color:#ff88cc;">75</td><td style="padding:4px 8px;"><b style="color:#ff88cc;">Devoted</b> — yours, and she knows it</td></tr>
<tr><td style="padding:4px 8px; color:#ff4444;">100</td><td style="padding:4px 8px;"><b style="color:#ff4444;">Vector</b> — one with the parasite; spreads it herself</td></tr>
</table>
<div style="background:#1a1400; border-left:3px solid #ffcc00; padding:8px 12px; margin:10px 0;">
<b style="color:#ffcc00;">The Cap.</b> Corruption cannot pass a ceiling — <b>25</b> at first. Raise it for everyone by buying <i>Universal Threshold</i> upgrades, or push one girl past it with the <b>Break Cap</b> button on her card. Breaking a cap is per-girl and permanent.
</div>
<p>Scenes change with corruption. The same location at 20 and at 90 is not the same scene.</p>
</div>
</details>
/* ═══════ 3. INFECTING ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ Infecting Girls
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<p>You must <b>meet</b> a girl before you can infect her. Three ways to meet:</p>
<ul style="margin:6px 0 12px 18px; line-height:1.8;">
<li><b style="color:#ccc;">Solo</b> — find her at one of her usual locations</li>
<li><b style="color:#ccc;">Group</b> — she appears at a fixed group meeting</li>
<li><b style="color:#ccc;">Contact</b> — needs an introduction from a girl at corruption 25+</li>
</ul>
<p style="color:#888; font-size:0.9em;">The Goals screen tells you exactly where to find anyone you haven't met.</p>
<hr style="border-color:#1e1e1e; margin:12px 0;">
<p><b style="color:#ccc;">Three methods:</b></p>
<table style="width:100%; border-collapse:collapse; margin:8px 0; font-size:0.92em;">
<tr style="color:#666;"><td style="padding:4px 8px;">Method</td><td style="padding:4px 8px;">Cost</td><td style="padding:4px 8px;">Chance</td><td style="padding:4px 8px;">Needs</td></tr>
<tr><td style="padding:4px 8px;"><b>Direct</b></td><td style="padding:4px 8px;">1</td><td style="padding:4px 8px;">60%</td><td style="padding:4px 8px; color:#777;">—</td></tr>
<tr><td style="padding:4px 8px;"><b>Exposure</b></td><td style="padding:4px 8px;">2</td><td style="padding:4px 8px;">95%</td><td style="padding:4px 8px; color:#777;">a spreading nest here</td></tr>
<tr><td style="padding:4px 8px;"><b>Vector</b></td><td style="padding:4px 8px;">1</td><td style="padding:4px 8px;">90%</td><td style="padding:4px 8px; color:#777;">a corrupted friend present</td></tr>
</table>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; padding:8px 12px; margin:10px 0;">
<b style="color:#bd59ff;">Nest level does not change the odds.</b> Exposure is 95% at a <i>Seedling</i> just as it is at a <i>Nexus</i> — the nest only has to exist, be spreading, and be at the location you are standing in. A breeding nest does not enable Exposure. Against an <b>Authority</b> girl, Direct drops to 40% and Exposure to 80%. The <i>Infection Success</i> upgrade adds a flat <b>+25%</b> to Direct.
</div>
<div style="background:#1a0000; border-left:3px solid #ff4444; padding:8px 12px; margin:10px 0;">
<b style="color:#ff4444;">Careful.</b> Failed attempts raise suspicion. Infecting in front of an <b>Authority</b> figure raises it a lot. <b>Authority</b> girls cannot be infected at all until you unlock <i>Authority Breach</i>.
</div>
<p><b style="color:#ccc;">Hivemind cap</b> limits how many girls you can hold infected at once — this applies to <i>everything</i>, including nests and passive spread. When it is full, <b>nothing new gets infected until you raise the cap</b>.</p>
<div style="background:#1a0d0d; border-left:3px solid #ff4444; padding:8px 12px; margin:10px 0;">
<b style="color:#44ff88;">Vectors still count.</b> A girl at <b>corr 100</b> occupies a slot like everyone else — she is the deepest hold you have, not a free one. What she gives you instead is reach: she spreads on her own overnight, the Lab cannot strip her, and if she is ever taken in they find nothing.
</div>
<div style="background:#1a0000; border-left:3px solid #ff5555; padding:8px 12px; margin:10px 0;">
<b style="color:#ff8888;">Slots never free up on their own.</b> Only two things take a girl out of the count: being <b>held captive</b>, and being <b>arrested</b>. A captive resumes her slot the day she is released, and releasing her raises your cap by <b>+1</b> to cover it. Plan the cap as a hard ceiling you have to keep buying upward.
</div>
<div style="background:#1a0a0a; border-left:3px solid #ff8866; padding:8px 12px; margin:10px 0;">
<b style="color:#ff8866;">Stuck?</b> Once the normal Hivemind upgrade is maxed for your level, an emergency <b>Strained Expansion</b> option appears in Upgrades. It is deliberately expensive and adds suspicion, but it guarantees you can never be permanently blocked.
</div>
</div>
</details>
/* ═══════ 4. NESTS ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ Nests
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<div style="background:#0a000f; border:1px solid #3a1a5a; border-radius:6px; padding:12px 14px; margin-bottom:14px; font-style:italic; color:#cc99ff; line-height:1.7;">
You think infection is something you <em>do</em> to them. It isn't. It is something that <em>happens</em> to them — the way mould takes a wall, not through one moment of contact but through days of quiet, invisible penetration.<br><br>
A nest is how I become the environment. Plant me in a place and I change what that place <em>is</em>. Every girl who walks in breathes a little of me.
</div>
<p>A nest turns a <i>place</i> into a weapon. Plant one and it works every night without you.</p>
<p><b style="color:#ccc;">Two types — choose when you plant:</b></p>
<ul style="margin:6px 0 12px 18px; line-height:1.8;">
<li><b style="color:#44ff88;">Spreading</b> — <b>2 parasites</b> (1 in a location you've dominated). Corrupts girls at that location and enables <b>Exposure</b> infection there. Can be upgraded and specialised.</li>
<li><b style="color:#ff88cc;">Breeding</b> — <b>1 parasite</b>. Produces <b>+1 parasite every night</b> (+2 with the <i>Breeding Boost</i> upgrade). Does not spread, does not enable Exposure, and cannot be upgraded or specialised. Like every nest it runs on a timer and dies when it expires, so it needs re-planting.</li>
</ul>
<table style="width:100%; border-collapse:collapse; margin:8px 0; font-size:0.9em;">
<tr style="color:#666;"><td style="padding:3px 8px;">Level</td><td style="padding:3px 8px;">Name</td><td style="padding:3px 8px;">Lasts</td><td style="padding:3px 8px;">Upgrade cost</td><td style="padding:3px 8px;">Detection</td></tr>
<tr><td style="padding:3px 8px;">1</td><td style="padding:3px 8px;">Seedling</td><td style="padding:3px 8px;">3d</td><td style="padding:3px 8px; color:#777;">3</td><td style="padding:3px 8px; color:#44ff88;">none</td></tr>
<tr><td style="padding:3px 8px;">2</td><td style="padding:3px 8px;">Colony</td><td style="padding:3px 8px;">5d</td><td style="padding:3px 8px; color:#777;">6 — must specialise</td><td style="padding:3px 8px; color:#88cc44;">2%</td></tr>
<tr><td style="padding:3px 8px;">3</td><td style="padding:3px 8px;">Stronghold</td><td style="padding:3px 8px;">8d</td><td style="padding:3px 8px; color:#777;">10</td><td style="padding:3px 8px; color:#ffcc00;">5%</td></tr>
<tr><td style="padding:3px 8px;">4</td><td style="padding:3px 8px;">Hive</td><td style="padding:3px 8px;">12d</td><td style="padding:3px 8px; color:#777;">15</td><td style="padding:3px 8px; color:#ff8800;">10%</td></tr>
<tr><td style="padding:3px 8px;">5</td><td style="padding:3px 8px;">Nexus</td><td style="padding:3px 8px;">18d</td><td style="padding:3px 8px; color:#777;">—</td><td style="padding:3px 8px; color:#ff4444;">18%</td></tr>
</table>
<p>Nests <b>decay</b> one day per night and vanish at zero. Above suspicion 50 they decay <b>2</b> a night, above 75 <b>3</b> a night — a high-suspicion run eats your nests as well as your girls. Upgrading resets the timer to the new level's full duration.</p>
<p><b style="color:#ccc;">Level 2 is a gate.</b> You cannot upgrade from Colony to Stronghold the normal way — you must pay 6 and pick a <b>specialisation</b>, and the choice is permanent:</p>
<ul style="margin:6px 0 12px 18px; line-height:1.8;">
<li><b style="color:#cc88ff;">Corruption</b> — the strongest deepener. <b>+3/+4/+5</b> corruption a night to every infected girl present at L3/L4/L5, and half that to infected girls who <i>anchor</i> here but happen to be elsewhere. Infects nobody new.</li>
<li><b style="color:#44aaff;">Spread</b> — <b>30%/40%/50%</b> chance a night to infect each uninfected girl present, at +2 corruption. The fastest way to grow the hivemind, and the fastest way to fill it.</li>
<li><b style="color:#88ff88;">Stealth</b> — detection cut to a quarter, suspicion from any detection halved, and it suppresses <b>50%/75%/100%</b> of the suspicion generated by your actions at that location. At <b>L5 it cannot be detected at all</b>. Only +1 corruption a night — you are buying safety, not speed.</li>
</ul>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; padding:8px 12px; margin:10px 0;">
<b style="color:#bd59ff;">Free upgrade.</b> A girl with corruption 75+ who has been <b>bred</b> and is standing at the nest can be spent to raise it a level for nothing — no parasites, no suspicion. It adds days rather than resetting them, and it can't cross the level 2 gate either.
</div>
<p style="color:#888; font-size:0.9em;">Your <b>nest cap</b> limits how many you can hold at once. Nests at <b>critical</b> locations need the <i>Critical Infrastructure</i> upgrade before you can plant at all.</p>
<hr style="border-color:#1e1e1e; margin:14px 0;">
<p><b style="color:#ccc;">What each place becomes at level 3+</b> — an unspecialised nest takes its effect from the location's type. Specialised nests use their specialisation instead and ignore this table.</p>
<div style="display:flex; flex-direction:column; gap:6px; margin:8px 0 12px;">
<div style="background:#111; border-radius:5px; padding:8px 10px; border-left:3px solid #44ff88;">
<div style="font-size:0.8em; font-weight:bold; color:#44ff88; margin-bottom:3px;">INTIMATE — 13 places (all homes, both dorms, the Harem Mansion, Hotel, Office, Spa)</div>
<div style="font-size:0.84em; color:#999; line-height:1.5;"><b>+1/+2/+3</b> corruption a night to infected girls inside, and it suppresses <b>20%/40%/60%</b> of the suspicion your actions there generate. Infects nobody new. Intimate nests are <b>never detected at any level</b> and are never raided — the safest ground in the game.</div>
</div>
<div style="background:#111; border-radius:5px; padding:8px 10px; border-left:3px solid #4488ff;">
<div style="font-size:0.8em; font-weight:bold; color:#4488ff; margin-bottom:3px;">ACADEMIC — 10 places (the five classes, Staff Room, Detention Room, Student Council, Library, Real Estate)</div>
<div style="font-size:0.84em; color:#999; line-height:1.5;">Routine is the weapon. <b>+1/+2/+3</b> a night to every infected girl who <i>anchors</i> here — she gets it whether or not she is present, and whether or not you are. Check a girl's card for her anchor. At <b>L5</b> it also has a 20% chance a night to newly infect each uninfected girl present, up to corruption 25.</div>
</div>
<div style="background:#111; border-radius:5px; padding:8px 10px; border-left:3px solid #ff8844;">
<div style="font-size:0.8em; font-weight:bold; color:#ff8844; margin-bottom:3px;">SOCIAL HUB — 9 places (Cafeteria, Gym, Club, Cinema, Arcade, Restaurant, Sorority House, Department Store, Clothing Store)</div>
<div style="font-size:0.84em; color:#999; line-height:1.5;">The all-rounder. <b>20%/30%/40%</b> chance a night to infect each uninfected girl present, and infected girls present gain <b>+1/+2/+3</b>. Newly seeded girls stop at corruption 25 until something else pushes them. This is also the default for any location without a listed type.</div>
</div>
<div style="background:#111; border-radius:5px; padding:8px 10px; border-left:3px solid #88ff44;">
<div style="font-size:0.8em; font-weight:bold; color:#88ff44; margin-bottom:3px;">OUTDOOR — 5 places (School Rooftop, Cheerleader Track, School Pool, Park, Beach)</div>
<div style="font-size:0.84em; color:#999; line-height:1.5;">The weakest. A flat <b>+1</b> a night to infected girls present, at every level, and it infects nobody. Detection still climbs with the level. Worth a Seedling for Exposure access, rarely worth upgrading unspecialised — specialise it instead.</div>
</div>
<div style="background:#111; border-radius:5px; padding:8px 10px; border-left:3px solid #ffcc00;">
<div style="font-size:0.8em; font-weight:bold; color:#ffcc00; margin-bottom:3px;">TRANSIENT — 4 places (Dormitory Hall, School Hallway, Town Square, Electronics Store)</div>
<div style="font-size:0.84em; color:#999; line-height:1.5;">Volume. <b>15%/25%/35%</b> chance a night to take hold of each uninfected girl passing through. She is infected the moment it lands and stops at corruption 25 until something else pushes her, so it does cost a hivemind slot. The cheapest way to widen the net, but every catch is a slot spent on someone you did not choose.</div>
</div>
<div style="background:#111; border-radius:5px; padding:8px 10px; border-left:3px solid #ff4444;">
<div style="font-size:0.8em; font-weight:bold; color:#ff4444; margin-bottom:3px;">CRITICAL — 3 places (Police Station, Courthouse, Town Hall)</div>
<div style="font-size:0.84em; color:#999; line-height:1.5;">Locked until you buy <i>Critical Infrastructure</i>. No special effect of its own — it falls back to social hub behaviour — but a nest inside the machinery that hunts you is worth having, and dominating one with the right upgrade makes it undetectable.</div>
</div>
</div>
<hr style="border-color:#1e1e1e; margin:14px 0;">
<div style="background:#1a0000; border-left:3px solid #ff4444; padding:8px 12px; margin:10px 0;">
<b style="color:#ff4444;">Detection.</b> Rolled once a night per nest. The table's percentage is the base — multiply by <b>1.5×</b> above suspicion 25, <b>2×</b> above 50, <b>3×</b> above 75. A Nexus during a crackdown is an 18% × 3 = better-than-even coin flip. Getting caught costs <b>10 + 5 per level</b> suspicion and knocks the nest down a level; from Seedling it destroys it outright. Above suspicion 50 police also raid, independently, at a flat 10% a night per nest. Intimate nests are exempt from all of it.
</div>
<p style="color:#888; font-size:0.9em;">Detective <b>Angel</b> is the one to watch. At suspicion 75+ she is the only officer in the game who patrols intimate locations — the nests are still safe, but you are not.</p>
</div>
</details>
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ Suspicion — the thing that kills you
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<p>One number, 0 to 100, shared across the whole town. <b style="color:#ff4444;">At 100 you lose.</b></p>
<table style="width:100%; border-collapse:collapse; margin:8px 0; font-size:0.92em;">
<tr><td style="padding:5px 8px; color:#44ff88; white-space:nowrap;"><b>0–24 CLEAR</b></td><td style="padding:5px 8px;">Nobody is looking.</td></tr>
<tr><td style="padding:5px 8px; color:#ffcc00; white-space:nowrap;"><b>25–49 ELEVATED</b></td><td style="padding:5px 8px;">A detective is assigned and starts appearing near infected girls.</td></tr>
<tr><td style="padding:5px 8px; color:#ff8800; white-space:nowrap;"><b>50–74 HIGH</b></td><td style="padding:5px 8px;">Parties cancelled. Police destroy nests. Critical locations close.</td></tr>
<tr><td style="padding:5px 8px; color:#ff2222; white-space:nowrap;"><b>75–99 DANGER</b></td><td style="padding:5px 8px;">Girls get arrested and sent to The Lab. Most public places close.</td></tr>
<tr><td style="padding:5px 8px; color:#ff0000; white-space:nowrap;"><b>100 CRITICAL</b></td><td style="padding:5px 8px;">Game over.</td></tr>
</table>
<p><b style="color:#ccc;">It rises from:</b> failed infections, acting in front of authority, nest detection, and arrests.</p>
<p><b style="color:#ccc;">It falls from:</b> quiet days, corrupted <b>Influential</b> girls, corrupted <b>Authority</b> figures, and certain upgrades.</p>
<div style="background:#1a1400; border-left:3px solid #ffcc00; padding:8px 12px; margin:10px 0;">
<b style="color:#ffcc00;">Arrested girls</b> go to The Lab and lose 10 corruption per night until they are clean and released. Losing a girl at 90 is expensive — watch the meter.
</div>
<div style="background:#12000a; border-left:3px solid #ff4444; padding:8px 12px; margin:10px 0;">
<b style="color:#ff4444;">Vectors are the exception.</b> A girl at <b>corr 100</b> can still be taken in, but there is no infection left in her to strip out — every test comes back clean. The Lab holds her <b>5 days</b> and lets her go, still infected, still at 100.
</div>
<p style="color:#888; font-size:0.9em;">Location type matters. <i>Intimate</i> places are far safer than <i>critical</i> ones.</p>
</div>
</details>
/* ═══════ 6. GIRL TRAITS ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ Girl Traits
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<p>Some girls are marked on their character card:</p>
<div style="margin:10px 0;">
<div style="margin-bottom:10px;">
<b style="color:#ffaa22;">⚖ Authority</b><br>
<span style="color:#999;">Police, professors, officials. Cannot be infected until you unlock <i>Authority Breach</i>. Infecting one is loud (+20 suspicion) — but once corrupted she <b>lowers</b> suspicion every day, and her presence no longer blocks you.</span>
</div>
<div style="margin-bottom:10px;">
<b style="color:#44aaff;">◈ Influential</b><br>
<span style="color:#999;">Well-connected. Noisier to infect (+8), but reduces suspicion once past corruption 50.</span>
</div>
<div>
<b style="color:#ff4444;">⚡ Flashpoint</b><br>
<span style="color:#999;">Volatile. Infecting her spikes suspicion (+12). Handle in private.</span>
</div>
</div>
<p style="color:#888; font-size:0.9em;">Untagged girls are ordinary — only +5 suspicion. Practise on them.</p>
</div>
</details>
/* ═══════ 7. GOALS ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ Goals
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<p>Goals pay <b style="color:#bd59ff;">parasites</b> and permanent bonuses. They are your main income beyond passive generation.</p>
<ul style="margin:6px 0 12px 18px; line-height:1.8;">
<li><b style="color:#44ddff;">Make Contact</b> — <b>two steps</b>: meet a named girl, then infect her. Meeting her alone only fills half the bar. The goal tells you where to find her: her usual haunt if she has one, the group she turns up with, or which girl you need to corrupt first to get an introduction. Once you have met her the hint switches to reminding you she still needs infecting — and warns you if the hivemind is full, since a full hivemind blocks the second half.</li>
<li><b style="color:#bd59ff;">Corruption</b> — bring a girl to a threshold.</li>
<li><b style="color:#ffcc00;">Faction</b> — corrupt an entire faction.</li>
<li><b style="color:#44aaff;">Spread</b> — total corrupted girls.</li>
<li><b style="color:#ff8844;">Group</b> — a whole social group. Big permanent rewards.</li>
<li><b style="color:#44ffaa;">Location</b> — dominate a place.</li>
</ul>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; padding:8px 12px; margin:10px 0;">
Contact and Corruption goals refill automatically. Others leave an <b>empty slot</b> you can fill for <b>5 parasites</b>. You can also <b>reroll</b> any goal for 5.
</div>
<p style="color:#888; font-size:0.9em;">Completed goals never come back.</p>
</div>
</details>
/* ═══════ 8. FACTIONS ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ Factions & Directives
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<p>Girls who spend time together at the same location will, on their own, form a <b>faction</b> — a named group with a leader and a home turf. You do not create them and you cannot stop them forming. They recruit, merge, split, fall apart and fight each other whether you are paying attention or not.</p>
<p>Left alone they are just scenery. Corrupted, they become the most efficient tool in the game: <b>a faction does work for you on nights you are somewhere else.</b></p>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; padding:8px 12px; margin:10px 0;">
<b style="color:#bd59ff;">Why bother:</b> infecting one girl costs a parasite and a visit. Dominating a faction of six gets you six girls who share a location, spread to each other, and can be ordered around from the menu.
</div>
<h4 style="color:#ccc; margin:14px 0 6px 0; font-size:0.95em;">Stance — how far they have fallen</h4>
<div style="margin:8px 0 12px 0; font-size:0.92em;">
<span style="color:#555;">NEUTRAL</span> →
<span style="color:#ffcc00;">UNEASY</span> →
<span style="color:#44ff88;">RECEPTIVE</span> →
<span style="color:#ff8844;">ENTHRALLED</span> →
<span style="color:#ff44ff;">DOMINATED</span>
</div>
<p>Stance is recalculated every night from the state of the members. You do not raise it directly — you raise it by corrupting the right people.</p>
<table style="width:100%; border-collapse:collapse; margin:8px 0; font-size:0.88em;">
<tr style="color:#666;"><td style="padding:3px 8px;">Stance</td><td style="padding:3px 8px;">Reached when</td></tr>
<tr><td style="padding:3px 8px; color:#ffcc00;"><b>Uneasy</b></td><td style="padding:3px 8px; color:#999;">any <b>1 member</b> is infected</td></tr>
<tr><td style="padding:3px 8px; color:#44ff88;"><b>Receptive</b></td><td style="padding:3px 8px; color:#999;"><b>2 members</b> infected, <i>or</i> any one member at <b>Corr 50</b></td></tr>
<tr><td style="padding:3px 8px; color:#ff8844;"><b>Enthralled</b></td><td style="padding:3px 8px; color:#999;"><b>half the members</b> at Corr 25, <i>or</i> leader at Corr 50 plus two members at Corr 50</td></tr>
<tr><td style="padding:3px 8px; color:#ff44ff;"><b>Dominated</b></td><td style="padding:3px 8px; color:#999;">the <b>leader</b> alone reaches <b>Corr 75</b></td></tr>
</table>
<div style="background:#0d1a0d; border-left:3px solid #44ff88; padding:8px 12px; margin:10px 0;">
<b style="color:#44ff88;">The shortcut:</b> Dominated ignores everyone else entirely — it only checks the leader. Taking one leader to 75 is far cheaper than grinding a whole group, and it unlocks the top tier of directives outright.
</div>
<h4 style="color:#ccc; margin:14px 0 6px 0; font-size:0.95em;">Directives — giving orders</h4>
<p>Directives are issued from the <b>Factions</b> screen. Each needs two things: the matching <b><i>Faction Directives</i></b> upgrade bought, and the faction at the required stance or higher.</p>
<p style="color:#888; font-size:0.9em;">Some are <b>instant</b> (they resolve immediately), others are <b>persistent</b> (they run for a set number of days). A faction runs one persistent directive at a time.</p>
<table style="width:100%; border-collapse:collapse; margin:8px 0; font-size:0.86em;">
<tr style="color:#666;"><td style="padding:3px 6px;">Tier</td><td style="padding:3px 6px;">Directive</td><td style="padding:3px 6px;">Effect</td></tr>
<tr><td style="padding:3px 6px; color:#88aaff;" rowspan="4"><b>T1</b><br><span style="font-size:0.85em; color:#666;">Uneasy</span></td>
<td style="padding:3px 6px; color:#ccc;">Shadow</td><td style="padding:3px 6px; color:#999;">All members roam to their anchor for 3 days — makes them predictable and easy to find.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Cover Story</td><td style="padding:3px 6px; color:#999;">−5 suspicion per day while active.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Mark Territory</td><td style="padding:3px 6px; color:#999;">Nest detection halved at their home location for 5 days.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Recruitment</td><td style="padding:3px 6px; color:#999;">The faction pulls in one unaffiliated girl tomorrow.</td></tr>
<tr><td style="padding:3px 6px; color:#44cc88;" rowspan="3"><b>T2</b><br><span style="font-size:0.85em; color:#666;">Receptive</span></td>
<td style="padding:3px 6px; color:#ccc;">Safe House</td><td style="padding:3px 6px; color:#999;">Nest at their home location cannot be detected or destroyed for 5 days.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Pressure</td><td style="padding:3px 6px; color:#999;">Every infected member gains <b>+3 corruption a day for 4 days</b>.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Force Party</td><td style="padding:3px 6px; color:#999;">They throw a party tomorrow — attend it to work the whole group at once.</td></tr>
<tr><td style="padding:3px 6px; color:#ffaa44;" rowspan="4"><b>T3</b><br><span style="font-size:0.85em; color:#666;">Enthralled</span></td>
<td style="padding:3px 6px; color:#ccc;">Expel Member</td><td style="padding:3px 6px; color:#999;">Kick a specific girl out of the faction.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Merge Factions</td><td style="padding:3px 6px; color:#999;">Fold another faction into this one — members and connections combine.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Split Faction</td><td style="padding:3px 6px; color:#999;">Break half the members off into a new faction.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Betrayal</td><td style="padding:3px 6px; color:#999;">The faction seizes one of its own — she is held <b>captive for 5 days</b>. Costs the faction 25 stability and you 10 suspicion. Cannot target the leader.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Infiltrate</td><td style="padding:3px 6px; color:#999;">Send a Corr 50+ unaffiliated girl to seize <b>any</b> faction, regardless of its stance.</td></tr>
<tr><td style="padding:3px 6px; color:#ff5555;" rowspan="3"><b>T4</b><br><span style="font-size:0.85em; color:#666;">Dominated</span></td>
<td style="padding:3px 6px; color:#ccc;">Concentrate</td><td style="padding:3px 6px; color:#999;">Force every member to their home location tomorrow.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Dismantle</td><td style="padding:3px 6px; color:#999;">Dissolve the faction. Everyone becomes unaffiliated.</td></tr>
<tr><td style="padding:3px 6px; color:#ccc;">Start Clash</td><td style="padding:3px 6px; color:#999;">Point this faction at another one and make them fight.</td></tr>
</table>
<h4 style="color:#ccc; margin:14px 0 6px 0; font-size:0.95em;">What they do without you</h4>
<ul style="margin:6px 0 12px 18px; line-height:1.8;">
<li><b style="color:#ccc;">Grow</b> — pull in unaffiliated girls who share a location with a member.</li>
<li><b style="color:#ccc;">Spread internally</b> — a receptive faction passes corruption between its own members. This is the passive engine you are paying for.</li>
<li><b style="color:#ccc;">Throw parties</b> — occasionally, on their own. Attending one lets you work every member in a single evening.</li>
<li><b style="color:#ccc;">Fight</b> — two factions claiming the same home location will eventually clash. The loser can be shattered.</li>
<li><b style="color:#ccc;">Fall apart</b> — low stability causes expulsions, leader changes, splits and outright disbanding.</li>
</ul>
<div style="background:#1a0d0d; border-left:3px solid #ff4444; padding:8px 12px; margin:10px 0;">
<b style="color:#ff8888;">Watch the leader.</b> Leadership can change hands if stability drops. If your Corr 75 leader gets replaced by someone clean, the faction falls out of Dominated and your T4 directives go with it.
</div>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; padding:8px 12px; margin:10px 0;">
<b style="color:#bd59ff;">Practical order:</b> pick one faction whose home location you can visit often → infect the leader → push her to 75 while a nest works on the rest → Dominated → use <i>Pressure</i> and <i>Force Party</i> to sweep the remaining members cheaply.
</div>
</div>
</details>
/* ═══════ 9. EVOLVING ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#12001a; border:1px solid #6a0dad; border-radius:6px; color:#bd59ff; font-weight:bold; font-size:0.95em;">
▸ Evolving the Parasite
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.7;">
<p>The <b>Upgrades</b> screen is where you spend parasites on permanent power. Four evolution levels, each unlocking a tier of upgrades:</p>
<table style="width:100%; border-collapse:collapse; margin:8px 0; font-size:0.92em;">
<tr style="color:#666;"><td style="padding:4px 8px;">Level</td><td style="padding:4px 8px;">Cost</td><td style="padding:4px 8px;">Requirement</td></tr>
<tr><td style="padding:4px 8px; color:#88aaff;"><b>2 Parasite</b></td><td style="padding:4px 8px;">10</td><td style="padding:4px 8px; color:#999;">3 girls at corruption 25</td></tr>
<tr><td style="padding:4px 8px; color:#44cc88;"><b>3 Hivemind</b></td><td style="padding:4px 8px;">25</td><td style="padding:4px 8px; color:#999;">1 Authority figure infected</td></tr>
<tr><td style="padding:4px 8px; color:#ffaa44;"><b>4 Dominant</b></td><td style="padding:4px 8px;">50</td><td style="padding:4px 8px; color:#999;">5 locations dominated</td></tr>
</table>
<p>Evolving also raises your <b>nest cap</b>, <b>hivemind cap</b> and <b>infection power</b> directly.</p>
<div style="background:#0d0d1a; border-left:3px solid #bd59ff; padding:8px 12px; margin:10px 0;">
<b style="color:#bd59ff;">Early priorities:</b> <i>Character Agenda</i> (see where everyone is), <i>Universal Threshold I</i> (raise the cap to 50), and a suspicion reduction for wherever you work most.
</div>
</div>
</details>
/* ═══════ 10. TIPS ═══════ */
<details style="margin-bottom:8px;">
<summary style="cursor:pointer; user-select:none; padding:10px 14px; background:#1a0030; border:1px solid #9c27b0; border-radius:6px; color:#ff88ff; font-weight:bold; font-size:0.95em;">
▸ Tips for a First Run
</summary>
<div style="background:#0a0a0a; border:1px solid #1e1e1e; border-top:none; border-radius:0 0 6px 6px; padding:14px 18px; color:#bbb; font-size:0.9em; line-height:1.8;">
<ol style="margin:0 0 0 18px;">
<li><b style="color:#ccc;">Start at home.</b> Intimate locations barely raise suspicion. Your household is the safest place to learn.</li>
<li><b style="color:#ccc;">Plant a breeding nest early.</b> It costs 1 parasite and pays +1 a night, which compounds fast. Keep an eye on its days remaining — when it runs out it is gone, and the income stops with it.</li>
<li><b style="color:#ccc;">Put your first spreading nest somewhere intimate.</b> Your house, your dorm. Intimate nests are never detected and never raided, they deepen everyone inside, and they quietly swallow a fifth of the suspicion everything you do there would otherwise cost.</li>
<li><b style="color:#ccc;">Don't touch Authority yet.</b> You can't infect them at first, and trying near them is costly.</li>
<li><b style="color:#ccc;">Read the Goals screen.</b> It tells you where unmet girls are — it's a map, not a checklist.</li>
<li><b style="color:#ccc;">Let suspicion fall.</b> A quiet day is a real move. Above 50 you start losing access; above 75 you start losing girls.</li>
<li><b style="color:#ccc;">Get one girl to 100.</b> A Vector spreads on her own and pays for herself.</li>
<li><b style="color:#ccc;">Check the night report.</b> It tells you what the world did while you slept.</li>
</ol>
</div>
</details>
<div style="text-align:center; margin-top:22px; color:#333; font-size:0.8em; font-style:italic;">
Press <b>?</b> anywhere for keyboard shortcuts.
</div>
</div>
[[← Back to the Hub|TownHub]]/* ─────────────────────────────────────────────────────────────────────────
SOLO MEETING SCENES — PART A
Included by SoloMeetingScenes. Do not link here directly: _mc and the
page header are set up by that passage.
Girls: maya, alex, ashly, caprice, blake, haley, ember, angel, jane,
avi, yulia, nancy, skylar, kate, anya, shazia
───────────────────────────────────────────────────────────────────────── */
<<if $meetingTarget is "maya">>
Maya is sitting on a bench, phone in hand. She pats the spot beside her.
<<speech "Maya">> "Hey. Sit with me." <</speech>>
She holds up her phone—a photo from last month. Eva stuck in a tree. Aria laughing below.
<<speech "Maya">> "Remember this?" <</speech>>
<<speech "$name">> "She claimed she meant to do that." <</speech>>
<<speech "Maya">> "She always claims that." <</speech>>
She laughs, scrolls to another. A group shot on a couch. You in the corner, half-smiling.
<<speech "Maya">> "I take a lot of photos. Someone has to remember the good parts." <</speech>>
She pockets her phone, stretches.
<<speech "Maya">> "Aria's been trying to get everyone together. You in?" <</speech>>
<<speech "$name">> "Depends on when." <</speech>>
<<speech "Maya">> "That's not a no." <</speech>>
She grins.
<<speech "Maya">> "Come on. Walk with me. I need coffee." <</speech>>
She's already moving, expecting you to follow.
<<elseif $meetingTarget is "alex">>
Alex is checking her phone, a half-empty cup in her other hand. She looks up when you approach.
<<speech "Alex">> "Hey." <</speech>>
She holds out her cup.
<<speech "Alex">> "Here. You look like you need it." <</speech>>
<<speech "$name">> "I'm fine." <</speech>>
<<speech "Alex">> "That's what people say when they're not fine." <</speech>>
She pockets her phone.
<<speech "Alex">> "I'm running the bake sale this weekend. Need people who can carry tables." <</speech>>
<<speech "$name">> "You're recruiting me for manual labor." <</speech>>
<<speech "Alex">> "I'm recruiting you for a good cause. You're going on the spring trip, right?" <</speech>>
<<speech "$name">> "Haven't decided." <</speech>>
<<speech "Alex">> "Decide faster. I need numbers for the bus." <</speech>>
She grins.
<<speech "Alex">> "Help with the sale and I'll stop bothering you about it. Deal?" <</speech>>
<<speech "$name">> "That's bribery." <</speech>>
<<speech "Alex">> "That's negotiation. Saturday. Cafeteria. Don't be late." <</speech>>
She's already walking away, phone back in her hand.
<<elseif $meetingTarget is "ashly">>
Ashly is sitting alone, a book open in her lap. She marks her page when you approach.
<<speech "Ashly">> "Hi." <</speech>>
<<speech "$name">> "What are you reading?" <</speech>>
She holds it up.
<<speech "Ashly">> "It's for class. I'm behind." <</speech>>
<<speech "$name">> "You're always reading for class." <</speech>>
<<speech "Ashly">> "I like reading. It's easier than talking to people." <</speech>>
She glances down, then back up.
<<speech "Ashly">> "That sounded weird." <</speech>>
<<speech "$name">> "No, it didn't." <</speech>>
She relaxes a little.
<<speech "Ashly">> "I'm trying to finish before Thursday. Professor Chanel said she might call on people." <</speech>>
<<speech "$name">> "She always says that." <</speech>>
<<speech "Ashly">> "I know. But I believe her every time." <</speech>>
She tucks the book into her bag.
<<speech "Ashly">> "I should go. I have to finish this chapter." <</speech>>
She hesitates.
<<speech "Ashly">> "If you need to borrow it, I'll be done by Friday." <</speech>>
She's gone before you can answer.
<<elseif $meetingTarget is "caprice">>
The library is quiet this time of day. Caprice is near the returns cart, a stack of books in her arms, moving with practiced efficiency.
<<speech "Caprice">> "You actually read, or you just come here for the silence?" <</speech>>
She doesn't look up from the cart.
<<speech "$name">> "Both." <</speech>>
<<speech "Caprice">> "Honest answer. Rare." <</speech>>
She slots a book into place, moves to the next.
<<speech "$name">> "Didn't know you worked here." <</speech>>
<<speech "Caprice">> "I help out. Shazia needed someone who can reach the top shelves." <</speech>>
She glances at you, then back at the cart.
<<speech "Caprice">> "You're here a lot. Never seen you check anything out though." <</speech>>
<<speech "$name">> "I read here." <</speech>>
<<speech "Caprice">> "That's not suspicious at all." <</speech>>
She says it flat, but there's a curve at the corner of her mouth.
She finishes the cart, leans against the shelf.
<<speech "Caprice">> "What do you read?" <</speech>>
<<speech "$name">> "Whatever's around." <</speech>>
<<speech "Caprice">> "That's not an answer." <</speech>>
<<speech "$name">> "It's the only one I have." <</speech>>
She studies you for a moment.
<<speech "Caprice">> "Fine. I'll pick something for you." <</speech>>
She moves down the aisle, fingers trailing over spines. Stops. Pulls one out. Tosses it to you.
<<speech "Caprice">> "That one. Come back when you're done. We'll see if you actually read it." <</speech>>
<<speech "$name">> "And if I do?" <</speech>>
<<speech "Caprice">> "Then I'll pick another." <</speech>>
She picks up the empty cart, pushes it toward the back.
<<speech "Caprice">> "Door's open whenever." <</speech>>
She disappears into the stacks.
<<elseif $meetingTarget is "blake">>
Blake is walking across the courtyard, a bag over her shoulder. She notices you first.
<<speech "Blake">> "Hey." <</speech>>
She slows, matches your pace.
<<speech "Blake">> "Marie's looking for you. She said to call her when you can." <</speech>>
<<speech "$name">> "I haven't checked my phone." <</speech>>
<<speech "Blake">> "She figured." <</speech>>
They fall into step.
<<speech "$name">> "What are you doing today?" <</speech>>
She holds up her bag.
<<speech "Blake">> "Groceries. Marie gave me a list. Very specific." <</speech>>
She smiles.
<<speech "Blake">> "If I get the wrong brand of anything, she'll know." <</speech>>
<<speech "$name">> "You two seem good together." <</speech>>
<<speech "Blake">> "We are. She plans. I'm flexible. It works." <</speech>>
She stops at the edge of the courtyard.
<<speech "Blake">> "I should go. Store closes at six." <</speech>>
She turns.
<<speech "Blake">> "Call Marie. She worries. Even when she shouldn't." <</speech>>
She walks off, already pulling out her phone.
<<elseif $meetingTarget is "haley">>
Haley is standing outside the building, scrolling through her phone. When she sees you, she waves.
<<speech "Haley">> "Come here." <</speech>>
She holds up her phone—a video of someone falling off a chair.
<<speech "Haley">> "My cousin. He was trying to be dramatic." <</speech>>
She pockets her phone.
<<speech "Haley">> "Walk with me. I have to pick up a gift for my mom." <</speech>>
She's already moving, and you follow.
<<speech "$name">> "What are you getting her?" <</speech>>
<<speech "Haley">> "I don't know yet. That's why I need you." <</speech>>
She grins.
<<speech "Haley">> "You're good at thoughtful. Everyone says so." <</speech>>
<<speech "$name">> "Who says that?" <</speech>>
<<speech "Haley">> "Aria. Eva. Emily. Basically everyone." <</speech>>
She nudges you.
<<speech "Haley">> "Help me pick something, and I'll owe you one." <</speech>>
<<speech "$name">> "You're going to owe me anyway." <</speech>>
<<speech "Haley">> "That's fine. I'm good at owing people." <</speech>>
She pulls open the door.
<<speech "Haley">> "Also, you're buying coffee. You owe me for dragging you out." <</speech>>
<<speech "$name">> "That's not how this works." <</speech>>
<<speech "Haley">> "It's how my version works." <</speech>>
She disappears inside, and you follow.
<<elseif $meetingTarget is "ember">>
Ember is standing outside the station, coffee in hand, watching the street. She glances at you as you pass, then does a double-take.
<<speech "Ember">> "Hold up." <</speech>>
You stop. She takes a step closer.
<<speech "Ember">> "You're the one who took in that girl. The one from the abuse case." <</speech>>
<<speech "$name">> "Emily. Yes." <</speech>>
<<speech "Ember">> "Heard about that. Social worker said you stepped up when no one else would." <</speech>>
She takes a slow sip of coffee.
<<speech "Ember">> "How's she doing?" <</speech>>
<<speech "$name">> "Better." <</speech>>
She nods slowly.
<<speech "Ember">> "Good. People like that—they need somewhere solid. Sounds like you gave her that." <</speech>>
She sets the cup down, folds her arms.
<<speech "Ember">> "You let me know if there's trouble. The family's been quiet, but that doesn't mean they're done." <</speech>>
<<speech "$name">> "I will." <</speech>>
She looks at you for a moment.
<<speech "Ember">> "You're young to be carrying that kind of weight. Taking someone in, making sure they're okay." <</speech>>
<<speech "$name">> "She needed help." <</speech>>
<<speech "Ember">> "Most people see someone who needs help and look the other way. You didn't." <</speech>>
She picks up her coffee again.
<<speech "Ember">> "That's not nothing." <</speech>>
She gestures down the street.
<<speech "Ember">> "Go on. I'm sure you've got places to be." <</speech>>
You start to walk.
<<speech "Ember">> "$name." <</speech>>
You look back.
<<speech "Ember">> "You ever need anything—for Emily, for yourself—you come find me. Door's open." <</speech>>
She's already looking at the street again.
<<elseif $meetingTarget is "angel">>
Angel is standing near the corner, notebook in hand, watching the intersection. She notices you approaching but doesn't acknowledge it until you're close.
<<speech "Angel">> "You live around here?" <</speech>>
<<speech "$name">> "Few blocks that way." <</speech>>
She nods, makes a note in her book.
<<speech "Angel">> "You notice anything strange lately? People acting out of sorts? Unusual activity?" <</speech>>
<<speech "$name">> "Strange how?" <</speech>>
She looks up.
<<speech "Angel">> "However it looks. People who seem different. Places that feel off. Anything that doesn't fit." <</speech>>
<<speech "$name">> "I haven't noticed anything." <</speech>>
She studies you for a beat, then nods.
<<speech "Angel">> "You would know if you saw it. Trust me." <</speech>>
She flips a page.
<<speech "Angel">> "There's been reports. Nothing concrete. Just... patterns. Things that don't add up." <</speech>>
She looks down the street.
<<speech "Angel">> "You keep your eyes open. You see something, you tell me. Not your teacher. Not your family. Me." <</speech>>
<<speech "$name">> "Why?" <</speech>>
<<speech "Angel">> "Because everyone thinks it's nothing. I'd know if it's something." <</speech>>
She closes her notebook.
<<speech "Angel">> "You seem like someone who pays attention. That's useful." <</speech>>
She tucks the notebook into her coat.
<<speech "Angel">> "If you hear anything—from anyone—you come find me." <</speech>>
She heads down the block, already scanning the street again.
<<elseif $meetingTarget is "jane">>
Jane is walking the block near the school, uniform crisp, eyes moving across windows and doorways. She smiles when she sees you.
<<speech "Jane">> "Afternoon. You heading home?" <</speech>>
<<speech "$name">> "Yeah." <</speech>>
She falls into step beside you.
<<speech "Jane">> "Good day for a walk. Warm for this time of year." <</speech>>
She glances at a house they're passing, then back at the street.
<<speech "Jane">> "You been in the area long? I'm still learning the neighborhood. Trying to get a feel for things." <</speech>>
<<speech "$name">> "Most of my life." <</speech>>
<<speech "Jane">> "Good. Then you'd notice if something was off." <</speech>>
She looks at you.
<<speech "Jane">> "We've been getting calls. Nothing big. People feeling uneasy. Strange noises at night. The kind of things people dismiss." <</speech>>
<<speech "$name">> "You think it's something?" <</speech>>
<<speech "Jane">> "I think people don't call unless they feel something's wrong." <</speech>>
She slows at the corner.
<<speech "Jane">> "You notice anything like that? Anything out of place?" <</speech>>
<<speech "$name">> "Not really." <</speech>>
She nods.
<<speech "Jane">> "Alright. If you do, you let us know. That's what we're here for." <</speech>>
She smiles again.
<<speech "Jane">> "Doesn't matter how small. Sometimes the small things are the ones that matter." <</speech>>
She glances down the side street.
<<speech "Jane">> "I should keep moving. You take care." <</speech>>
She heads off, boots steady on the pavement.
<<elseif $meetingTarget is "avi">>
She's at a table in the corner of the cafeteria, books spread out, pen moving fast. She doesn't look up when you sit down.
<<speech "Avi">> "You're late." <</speech>>
<<speech "$name">> "I'm not scheduled to tutor you today." <</speech>>
She glances up.
<<speech "Avi">> "So why are you here?" <</speech>>
<<speech "$name">> "Eating." <</speech>>
You hold up the sandwich you bought. She snorts.
<<speech "Avi">> "Fine. But since you're here." <</speech>>
She shoves a textbook toward you.
<<speech "Avi">> "This chapter. Make it make sense." <</speech>>
She leans back, arms crossed, watching.
<<speech "$name">> "You could just read it." <</speech>>
<<speech "Avi">> "I could. I won't. That's why I have a tutor." <</speech>>
She taps the page with her pen.
<<speech "Avi">> "Go. Fast. I have places to be." <</speech>>
<<elseif $meetingTarget is "yulia">>
She's sitting on a bench outside the library, a book open in her lap. She looks up when you approach, offers a small nod.
You sit on the other end.
<<speech "Yulia">> "Hello, $name." <</speech>>
<<speech "$name">> "Hey. What are you reading?" <</speech>>
She holds up the cover. Another language.
<<speech "Yulia">> "A novel. From home." <</speech>>
<<speech "$name">> "Is it good?" <</speech>>
<<speech "Yulia">> "Yes. The characters argue a lot. I find it entertaining." <</speech>>
She closes the book.
<<speech "Yulia">> "You live nearby, yes? I see you walking in the mornings." <</speech>>
<<speech "$name">> "Few blocks that way." <</speech>>
<<speech "Yulia">> "It is a nice neighborhood. Quiet." <</speech>>
<<speech "$name">> "You like quiet?" <</speech>>
<<speech "Yulia">> "I like being able to hear myself think." <</speech>>
She stands, tucks the book under her arm.
<<speech "Yulia">> "I have class. Tell Emily I said hello." <</speech>>
<<speech "$name">> "I will." <</speech>>
She walks off, steps light.
<<elseif $meetingTarget is "nancy">>
She's standing outside the sorority house, checking her phone. She glances up when you approach.
<<speech "Nancy">> "$name. You're not here for rush, are you?" <</speech>>
<<speech "$name">> "Wrong gender." <</speech>>
<<speech "Nancy">> "And age. You'd be the youngest pledge by about three years." <</speech>>
She pockets her phone.
<<speech "Nancy">> "What are you doing here?" <</speech>>
<<speech "$name">> "Walking. What are you doing out here?" <</speech>>
<<speech "Nancy">> "Avoiding a meeting." <</speech>>
She leans against the railing.
<<speech "Nancy">> "Marie's inside. She's handling it." <</speech>>
<<speech "$name">> "You trust her to handle it?" <</speech>>
She shrugs.
<<speech "Nancy">> "She's good with people. Better than me. I just make sure everything works." <</speech>>
She looks at the house, then back at you.
<<speech "Nancy">> "You going to the spring formal? Marie's been organizing." <</speech>>
<<speech "$name">> "Haven't decided." <</speech>>
<<speech "Nancy">> "You should. She's putting a lot of work into it." <</speech>>
She pushes off the railing.
<<speech "Nancy">> "I should go. Meeting's probably over by now." <</speech>>
She heads inside.
<<elseif $meetingTarget is "skylar">>
She's behind the counter at the boutique, arranging a display. She looks up when you enter.
<<speech "Skylar">> "Hey. Looking for something?" <</speech>>
<<speech "$name">> "Just browsing." <</speech>>
She nods, goes back to her display.
<<speech "Skylar">> "We just got the spring stuff in. New colors, new cuts." <</speech>>
She holds up a shirt.
<<speech "Skylar">> "This one's been popular." <</speech>>
You take it. Nice fabric.
<<speech "$name">> "You pick out what comes in?" <</speech>>
<<speech "Skylar">> "Some of it. Manager makes the final call, but I put in suggestions." <</speech>>
She picks up her clipboard.
<<speech "Skylar">> "You going to the formal? We've been selling a lot for it." <</speech>>
<<speech "$name">> "Maybe." <</speech>>
<<speech "Skylar">> "If you do, come back before Friday. I can set something aside." <</speech>>
She makes a note on her clipboard.
<<speech "Skylar">> "We close in twenty." <</speech>>
<<elseif $meetingTarget is "kate">>
She's sitting on a low wall near the mall entrance, camera in her lap, scrolling. She looks up when you pass.
<<speech "Kate">> "Hey. Want to see something?" <</speech>>
She holds up the camera. A kid falling off a skateboard.
<<speech "$name">> "Did you get that for the mall page?" <</speech>>
She grins.
<<speech "Kate">> "No. That one's for me." <</speech>>
She scrolls to another shot. Sunset through the glass ceiling.
<<speech "Kate">> "This one's for work." <</speech>>
<<speech "$name">> "Same place?" <</speech>>
<<speech "Kate">> "Same place. Different eye." <</speech>>
She lowers the camera.
<<speech "Kate">> "What are you doing here?" <</speech>>
<<speech "$name">> "Walking." <</speech>>
<<speech "Kate">> "You do a lot of that." <</speech>>
She stands.
<<speech "Kate">> "I'm getting food. Want to come?" <</speech>>
<<speech "$name">> "Maybe next time." <</speech>>
<<speech "Kate">> "Your loss. The pretzel place is actually good." <</speech>>
She heads toward the doors.
<<speech "Kate">> "If you change your mind, you know where to find me." <</speech>>
She waves and disappears inside.
<<elseif $meetingTarget is "anya">>
<p>She's coming out of the staff room, a stack of papers in her hands. She stops when she sees you.</p>
<<speech "Anya">> "$name." <</speech>>
<p>She shifts the papers to one arm.</p>
<<speech "Anya">> "You're not in trouble. Don't look so worried." <</speech>>
<<speech "$name">> "Wasn't worried." <</speech>>
<p>She raises an eyebrow.</p>
<<speech "Anya">> "Sure." <</speech>>
<p>She glances at the papers, then back at you.</p>
<<speech "Anya">> "You've been around Aria lately?" <</speech>>
<<speech "$name">> "Yeah. Why?" <</speech>>
<<speech "Anya">> "No reason. She's been in a good mood. Thought it might be your doing." <</speech>>
<p>She shifts the papers again.</p>
<<speech "Anya">> "You going to the formal? She's been talking about it." <</speech>>
<<speech "$name">> "Probably." <</speech>>
<p>She nods.</p>
<<speech "Anya">> "Good. She'd be annoyed if you didn't show." <</speech>>
<p>She starts walking.</p>
<<speech "Anya">> "Don't be late picking her up. I'll know." <</speech>>
<p>She disappears down the hall.</p>
<<elseif $meetingTarget is "shazia">>
<p>She's behind the library counter, stamping books. She looks up when you approach, offers a small, nervous smile.</p>
<<speech "Shazia">> "Oh. Hello." <</speech>>
<p>She sets the stamp down.</p>
<<speech "Shazia">> "Did you need something? A book? I can help you find it." <</speech>>
<<speech "$name">> "Just looking." <</speech>>
<p>She nods quickly.</p>
<<speech "Shazia">> "Of course. Take your time. The new arrivals are on the table. If you want to... look at those." <</speech>>
<p>She gestures toward a table near the window. A stack of books, neatly arranged.</p>
<<speech "$name">> "You run the place by yourself?" <</speech>>
<<speech "Shazia">> "Oh, no. Caprice helps. She's very good at it." <</speech>>
<p>She picks up the stamp, sets it down again.</p>
<<speech "Shazia">> "She's not here today. Classes." <</speech>>
<<speech "$name">> "So it's just you." <</speech>>
<p>She smiles, small.</p>
<<speech "Shazia">> "I don't mind. It's quiet. I like quiet." <</speech>>
<p>She looks at the stack of books waiting to be stamped.</p>
<<speech "Shazia">> "If you need anything, I'll be here." <</speech>>
<p>She goes back to her work.</p>
<<else>>
You introduce yourself. <<print _mc.name>> gives a polite nod.
<</if>>
/* ─────────────────────────────────────────────────────────────────────────
SOLO MEETING SCENES — PART B
Included by SoloMeetingScenes. Do not link here directly: _mc and the
page header are set up by that passage.
Girls: alina, amber, luna, kailey, winter, melissa, vina, jessa, nikki,
veruca, keisha, may, natalia, natalie, uma, carolina, mia, riley,
myra, casey, harmony
───────────────────────────────────────────────────────────────────────── */
<<if $meetingTarget is "alina">>
<p>She's behind the front desk at the gym, checking something on a clipboard. She looks up when you walk in.</p>
<<speech "Alina">> "Here to work out?" <</speech>>
<<speech "$name">> "Just looking around." <</speech>>
<p>She sets the clipboard down.</p>
<<speech "Alina">> "Eva mentioned you might come by. She said you've been... quiet lately." <</speech>>
<p>She studies you for a moment.</p>
<<speech "Alina">> "You okay?" <</speech>>
<<speech "$name">> "I'm fine." <</speech>>
<p>She doesn't look convinced, but she doesn't push.</p>
<<speech "Alina">> "If you want to use the equipment, let me know. I can show you around." <</speech>>
<<speech "$name">> "Maybe another time." <</speech>>
<p>She nods.</p>
<<speech "Alina">> "Eva's been asking about you. You should call her. She worries." <</speech>>
<p>She picks up her clipboard.</p>
<<speech "Alina">> "She's dramatic about it, but she means well." <</speech>>
<p>She goes back to her paperwork.</p>
<<elseif $meetingTarget is "amber">>
<p>She's sitting at her desk in the empty classroom, grading papers. She looks up when you knock on the doorframe.</p>
<<speech "Amber">> "Come in." <</speech>>
<p>She sets her pen down.</p>
<<speech "Amber">> "You're not here about your grade, are you? Because you're doing fine in my class." <</speech>>
<<speech "$name">> "No. Just passing by." <</speech>>
<p>She leans back in her chair.</p>
<<speech "Amber">> "Passing by an empty classroom? That's a new one." <</speech>>
<p>She smiles.</p>
<<speech "Amber">> "How are things? You look tired." <</speech>>
<<speech "$name">> "I'm fine. Just busy." <</speech>>
<p>She nods slowly.</p>
<<speech "Amber">> "Well, make sure you're getting enough sleep. The end of the semester is coming up. I don't want to see your grades slipping." <</speech>>
<p>She picks up her pen.</p>
<<speech "Amber">> "You're in Chanel's class too, right? She's been talking about your essays." <</speech>>
<<speech "$name">> "Good things, I hope." <</speech>>
<p>She laughs.</p>
<<speech "Amber">> "She doesn't talk about the bad ones. So you're safe." <</speech>>
<p>She gestures at the stack of papers.</p>
<<speech "Amber">> "I should get back to these. Midterms are not going to grade themselves." <</speech>>
<p>She picks up the next paper.</p>
<<speech "Amber">> "Take care of yourself, $name. That's an order." <</speech>>
<p>She's smiling as she says it.</p>
<<elseif $meetingTarget is "luna">>
She's in the mansion garden, kneeling by a flower bed. She looks up when you approach the gate.
<<speech "Luna">> "Hello there." <</speech>>
She removes her gloves, stands.
<<speech "$name">> "Hi. Just walking through." <</speech>>
She nods.
<<speech "Luna">> "You're Haley's friend, right? She's mentioned you." <</speech>>
<<speech "$name">> "$name." <</speech>>
<<speech "Luna">> "I'm Luna. You probably figured that out." <</speech>>
She gestures at the garden.
<<speech "Luna">> "Do you garden?" <</speech>>
<<speech "$name">> "Not really." <</speech>>
<<speech "Luna">> "It's relaxing. Good for clearing your head." <</speech>>
She picks up a watering can.
<<speech "Luna">> "You're welcome to walk around. Just don't step on the roses. They've been temperamental." <</speech>>
She waters a cluster of flowers.
<<speech "$name">> "It's a nice garden." <</speech>>
<<speech "Luna">> "Thank you. It takes work, but I enjoy it." <</speech>>
She looks toward the house.
<<speech "Luna">> "If you see Haley, tell her I'm making lemon cake this weekend. She usually stops by." <</speech>>
<<speech "$name">> "I'll let her know." <</speech>>
<<speech "Luna">> "Good. She'd hate to miss it." <</speech>>
She smiles, goes back to her watering.
<<elseif $meetingTarget is "kailey">>
<<speech "Kailey">> "Hey! Over here." <</speech>>
She pats the spot next to her.
<<speech "Kailey">> "Sit. I need a break from watching all these people rush around." <</speech>>
You sit.
<<speech "Kailey">> "I feel like I haven't seen you in forever. What've you been up to?" <</speech>>
<<speech "$name">> "This and that." <</speech>>
She tilts her head, studying you.
<<speech "Kailey">> "You seem... different. I don't know. Quieter?" <</speech>>
<<speech "$name">> "Just tired." <</speech>>
She nods slowly.
<<speech "Kailey">> "Okay. Well, if you ever want to talk about it, I'm around." <</speech>>
She nudges your shoulder.
<<speech "Kailey">> "That's what friends are for, right?" <</speech>>
She grins.
<<speech "Kailey">> "Anyway, I should go. Mom's expecting me for dinner. But don't be a stranger, yeah?" <</speech>>
She stands, stretches.
<<speech "Kailey">> "See you around, $name." <</speech>>
She waves and disappears into the crowd.
<<elseif $meetingTarget is "winter">>
<<speech "Winter">> "$name. You're not in trouble, are you?" <</speech>>
<<speech "$name">> "No. Just walking." <</speech>>
She nods, tucks her phone into her coat.
<<speech "Winter">> "Good. Keep it that way." <</speech>>
She studies you for a moment.
<<speech "Winter">> "You look like Jewelz. Same tired eyes." <</speech>>
She shifts her briefcase to the other hand.
<<speech "Winter">> "How are things at home? Everyone okay?" <</speech>>
<<speech "$name">> "Yeah. Everyone's fine." <</speech>>
<<speech "Winter">> "Good. Tell Lana to call me sometime. She never answers her phone." <</speech>>
She glances at her watch.
<<speech "Winter">> "I have to go. Take care of yourself." <</speech>>
She walks off without looking back.
<<elseif $meetingTarget is "melissa">>
<<speech "Melissa">> "$name! There you are." <</speech>>
She pulls you into a quick hug before you can react.
<<speech "Melissa">> "I was just thinking about you. You look thin. Are you eating enough?" <</speech>>
<<speech "$name">> "I'm fine." <</speech>>
<<speech "Melissa">> "You always say that." <</speech>>
She holds up the bag.
<<speech "Melissa">> "Here. Take these. I bought too many anyway." <</speech>>
She presses the bag into your hands.
<<speech "Melissa">> "And come by the house this week. I want to see you. Really see you, not just bump into you." <</speech>>
She pats your cheek.
<<speech "Melissa">> "You're a good boy, $name. Don't forget that." <</speech>>
She heads off before you can argue.
<<elseif $meetingTarget is "vina">>
<<speech "Vina">> "Well, look who it is." <</speech>>
She pockets her phone.
<<speech "Vina">> "I was just thinking about you. Saw Elsa the other day. She said you've been busy." <</speech>>
<<speech "$name">> "Something like that." <</speech>>
<<speech "Vina">> "You should come by the house sometime. Mom's been asking about you." <</speech>>
She stands, brushes off her jeans.
<<speech "Vina">> "Same old Vina, by the way. Nothing's changed." <</speech>>
She smiles.
<<speech "Vina">> "Anyway, I should go. But don't be a stranger, okay?" <</speech>>
She waves and heads off.
<<elseif $meetingTarget is "jessa">>
She's walking out of a building, briefcase in hand, heels clicking on the pavement. She slows when she sees you.
<<speech "Jessa">> "You're Winter's cousin, aren't you?" <</speech>>
<<speech "$name">> "That's right." <</speech>>
She tilts her head, assessing.
<<speech "Jessa">> "She mentioned you. Said you're the quiet one. The one who actually listens." <</speech>>
She shifts her briefcase.
<<speech "Jessa">> "I'm Jessa. I work with Winter. She talks about her family more than she'd admit." <</speech>>
A small smile.
<<speech "Jessa">> "If you ever need legal advice — or just someone to tell you when something's a bad idea — I'm around." <</speech>>
She glances at her watch.
<<speech "Jessa">> "I have a hearing in twenty. Take care of yourself." <</speech>>
She walks off, purposeful.
<<elseif $meetingTarget is "veruca">>
The resource room is cluttered but organized — posters on the walls, books stacked neatly, a desk covered in papers. Veruca looks up from her work when you knock on the open door.
<<speech "Veruca">> "$name! Come in." <</speech>>
She sets down her pen, smiling.
<<speech "Veruca">> "I was hoping you'd stop by. I've been meaning to ask — how's that history project going? The one you were struggling with?" <</speech>>
<<speech "$name">> "Better. I think I'm getting it." <</speech>>
<<speech "Veruca">> "Good. You know where to find me if you need help." <</speech>>
She gestures around the room.
<<speech "Veruca">> "I'm always here. Well, not always, but usually." <</speech>>
She laughs softly at herself.
<<speech "Veruca">> "I've seen you in the hallways a lot. You always seem like you're in a hurry." <</speech>>
<<speech "$name">> "Just trying to get things done." <</speech>>
<<speech "Veruca">> "I get that. But don't forget to slow down sometimes." <</speech>>
She picks up her pen again.
<<speech "Veruca">> "Anyway, I won't keep you. But seriously — if you ever need help, or just a quiet place to work, you know where to find me." <</speech>>
<<elseif $meetingTarget is "keisha">>
She's standing near the Town Square fountain, clipboard in hand, scanning the area with a practiced eye. She spots you and gestures you over.
<<speech "Keisha">> "You. You're the one who helps deliver stuff from the college, right?" <</speech>>
<<speech "$name">> "Yeah. That's me." <</speech>>
She makes a note on her clipboard.
<<speech "Keisha">> "Good. You're reliable. I've noticed." <</speech>>
She looks up, studies you for a moment.
<<speech "Keisha">> "You look like you've got a lot on your mind. That's fine. Just don't let it slow you down." <</speech>>
She tucks the clipboard under her arm.
<<speech "Keisha">> "I'm Keisha. I handle events, permits, pretty much everything that keeps this town running. If you ever need anything — info, a favor, someone to point you in the right direction — you come find me." <</speech>>
She nods once, decisive.
<<speech "Keisha">> "Now get going. I'm sure you've got places to be." <</speech>>
She's already turning back to her clipboard.
<<elseif $meetingTarget is "may">>
The cinema lobby is quiet, the next show still half an hour away. Behind the counter, a girl in her late teens leans on her elbows, scrolling through her phone with obvious boredom.
She glances up when you approach, then back at her screen.
<<speech "May">> "Movies start at quarter past. Concessions are overpriced. Bathrooms are down the hall." <</speech>>
She pockets her phone, finally giving you her full attention.
<<speech "May">> "You look lost. First time here?" <</speech>>
<<speech "$name">> "Just looking." <</speech>>
She raises an eyebrow.
<<speech "May">> "People don't 'just look' at a cinema. You either buy a ticket or you're waiting for someone." <</speech>>
She leans on the counter.
<<speech "May">> "So? Which is it?" <</speech>>
<<speech "$name">> "Waiting." <</speech>>
She nods slowly.
<<speech "May">> "Alright. Well, if you change your mind, I'm here until closing. Try the popcorn. It's the only thing we don't mess up." <</speech>>
She goes back to her phone, but there's a slight curve to her mouth.
<<elseif $meetingTarget is "natalia">>
The arcade is alive with the beeps and blips of machines. Colorful lights flash from every corner. Behind the counter, a woman in her late twenties is adjusting a cosplay headpiece, her outfit a vivid mix of fantasy and gaming style. She looks up when you enter, a bright smile spreading across her face.
<<speech "Natalia">> "Welcome to the arcade! Home of high scores, low stakes, and the best vibes in town." <</speech>>
She gestures around the room.
<<speech "Natalia">> "I'm Natalia. I run this place. You look new — or at least new to actually stopping and looking around." <</speech>>
She studies you, her head tilted.
<<speech "Natalia">> "I've seen you pass by. You're always in a hurry." <</speech>>
<<speech "$name">> "Delivery stuff." <</speech>>
She nods, understanding.
<<speech "Natalia">> "Well, in here, there's no rush. That's the rule." <</speech>>
She gestures to the machines.
<<speech "Natalia">> "This is my sanctuary. I've been running it for years. Cosplaying, gaming, just... being myself. And I make sure everyone else can do the same." <</speech>>
She picks up a controller, holds it out to you.
<<speech "Natalia">> "First game's on me. Pick whatever you want — I've played them all." <</speech>>
She grins.
<<speech "Natalia">> "And if you beat my high score, I'll be genuinely impressed. No one has yet." <</speech>>
<<elseif $meetingTarget is "natalie">>
She's sitting at a table in the corner of the campus library, surrounded by stacks of papers and open books. Her laptop glows, and she's typing quickly, clearly focused. She doesn't notice you at first.
You approach the table, looking for a seat. She glances up briefly.
<<speech "Natalie">> "If you're looking for a place to sit, there are other tables. This one's occupied." <</speech>>
She goes back to typing.
<<speech "$name">> "I'm just looking for a book. I didn't mean to interrupt." <</speech>>
She pauses, looks at you again. A slight nod.
<<speech "Natalie">> "Fine. Just don't make noise." <</speech>>
She returns to her work.
A few minutes pass. She doesn't look up.
<<speech "Natalie">> "You're not finding it, are you?" <</speech>>
<<speech "$name">> "I don't know the section." <</speech>>
She sighs, stands, and walks over to a shelf. She pulls out a book, hands it to you.
<<speech "Natalie">> "That one. Now you can leave me alone." <</speech>>
She sits back down.
A pause.
<<speech "Natalie">> "I'm Natalie, by the way. If you're going to keep showing up here, it helps to know who you're annoying." <</speech>>
<<elseif $meetingTarget is "uma">>
She spots you watching and grins, tossing a ball your way. You catch it.
<<speech "Uma">> "Hey! Good reflexes!" <</speech>>
She waves you closer.
<<speech "Uma">> "You look like you need a distraction. Come on, join me." <</speech>>
She catches the ball you toss back.
<<speech "Uma">> "It's rare for us to meet outside. I perform here on good days. And even on bad days, honestly." <</speech>>
She laughs.
<<speech "Uma">> "This is my spot if you ever want to laze around. I'm hard to miss." <</speech>>
She gestures at her guitar.
<<speech "Uma">> "You play?" <</speech>>
<<speech "$name">> "No." <</speech>>
<<speech "Uma">> "Shame. But you're a good audience. That counts." <</speech>>
She starts playing a simple tune.
<<speech "Uma">> "If you stick around, you might learn something. Or you might just hear a good song. Either way, you're welcome." <</speech>>
<<elseif $meetingTarget is "carolina">>
She almost bumps into you, then stops.
<<speech "Carolina">> "Oh! Sorry. I'm not looking where I'm going." <</speech>>
She shifts the flyers, offering a slightly apologetic smile.
<<speech "Carolina">> "You're in my history class, right? I've seen you around." <</speech>>
<<speech "$name">> "Yeah. You're the mayor's daughter." <</speech>>
<<speech "Carolina">> "That's one way to describe me." <</speech>>
She rolls her eyes, but it's not aimed at you.
<<speech "Carolina">> "I'm Carolina, by the way. In case you didn't know." <</speech>>
She gestures at the flyers.
<<speech "Carolina">> "I help out here sometimes. My mom's always busy, so I pick up the slack." <</speech>>
She studies you for a moment.
<<speech "Carolina">> "You help with deliveries, right? I've seen you around. You always seem to be in a hurry." <</speech>>
<<speech "$name">> "Just trying to get things done." <</speech>>
<<speech "Carolina">> "I get that. Me too." <</speech>>
She shifts the flyers again.
<<speech "Carolina">> "If you ever need a hand with something, let me know. I'm usually around here." <</speech>>
<<elseif $meetingTarget is "mia">>
Her office is quiet, warm, and welcoming — soft lighting, plants on the windowsill, a comfortable chair across from her desk. She's reading a file when you knock on the open door.
She looks up with a gentle smile.
<<speech "Mia">> "$name. Come in." <</speech>>
She sets the file aside, gesturing to the chair.
<<speech "Mia">> "You don't usually stop by. Is everything okay?" <</speech>>
<<speech "$name">> "Everything's fine. Just wanted to say hi." <</speech>>
She studies you for a moment, her eyes kind but observant.
<<speech "Mia">> "You've been helping out around school a lot lately. People notice." <</speech>>
She leans forward slightly.
<<speech "Mia">> "If you ever need someone to talk to — about anything — my door is always open. It doesn't have to be a crisis." <</speech>>
She smiles again.
<<speech "Mia">> "Sometimes it's nice just to have a quiet place to sit." <</speech>>
She gestures around the room.
<<speech "Mia">> "This is that place, if you need it." <</speech>>
<<elseif $meetingTarget is "riley">>
She's leaning against the lockers, scrolling through her phone, a half-empty coffee cup balanced on the ledge beside her. She looks up when she hears footsteps, and her face breaks into a grin.
<<speech "Riley">> "$name! There you are." <</speech>>
She pockets her phone, grabbing her coffee.
<<speech "Riley">> "Eva's been looking for you. She said you were supposed to meet her after class." <</speech>>
<<speech "$name">> "I was. I got held up." <</speech>>
<<speech "Riley">> "Story of your life." <</speech>>
She falls into step beside you, walking easily.
<<speech "Riley">> "Anyway, she's with Chanel right now. Something about an assignment. So you've got time to explain to me why you've been avoiding me." <</speech>>
She grins, clearly teasing.
<<speech "$name">> "I haven't been avoiding you." <</speech>>
<<speech "Riley">> "Really? Because I've been around. You've been invisible." <</speech>>
She nudges your shoulder.
<<speech "Riley">> "It's fine. I know you're busy. Eva's the same way. You two are perfect for each other." <</speech>>
She takes a sip of her coffee.
<<speech "Riley">> "Seriously though — we should hang out soon. Just the three of us. Like old times." <</speech>>
<<speech "$name">> "That sounds good." <</speech>>
<<speech "Riley">> "You mean it this time?" <</speech>>
She raises an eyebrow.
<<speech "$name">> "I mean it." <</speech>>
She smiles, satisfied.
<<speech "Riley">> "Good. Because I'll hold you to it." <</speech>>
She stops at the end of the hall.
<<speech "Riley">> "I'm heading to the library. Tell Eva I said hi, and that she owes me for covering for her." <</speech>>
She waves, already walking backward.
<<speech "Riley">> "Don't be a stranger, $name. Seriously." <</speech>>
<<elseif $meetingTarget is "nikki">>
The spa is quiet, soft music playing from hidden speakers, the air smelling of lavender and eucalyptus. A woman in her late 30s looks up from the front desk as you enter, her eyes calm and assessing.
<<speech "Nikki">> "Welcome." <</speech>>
She sets down a small notebook, offering a gentle smile.
<<speech "Nikki">> "You must be $name. I've seen you around town." <</speech>>
<<speech "$name">> "Yeah. I help with deliveries sometimes." <</speech>>
She nods slowly, studying you with quiet attention.
<<speech "Nikki">> "I'm Nikki. I run this place." <</speech>>
She gestures around the room.
<<speech "Nikki">> "You look like you could use a break. Most people who walk through that door do." <</speech>>
<<speech "$name">> "I'm just looking." <</speech>>
<<speech "Nikki">> "That's what they all say." <</speech>>
She smiles, not pushing.
<<speech "Nikki">> "I've been doing this for years. I can tell when someone's carrying weight they don't need to." <</speech>>
She tilts her head.
<<speech "Nikki">> "If you ever want to put that weight down for a while, you know where to find me." <</speech>>
She slides a small card across the counter.
<<speech "Nikki">> "First session's on me. No pressure. Just a quiet hour to let yourself breathe." <</speech>>
She returns to her notebook, but her smile lingers.
<<elseif $meetingTarget is "myra">>
Myra is on the floor of the common area with her back against the sofa and one leg stretched out, earbuds in. She lifts a hand without looking up.
<<speech "Myra">> "They're out." <</speech>>
<<speech "$name">> "I know." <</speech>>
<<speech "Myra">> "Then sit down, you're looming." <</speech>>
You sit. She pulls one earbud out and lets it hang.
<<speech "Myra">> "Marie's dragged Blake to the big supermarket. The one across town." <</speech>>
<<speech "$name">> "Why that one?" <</speech>>
<<speech "Myra">> "Because the near one didn't have the right olives, and Blake said the olives don't matter, and Marie went quiet." <</speech>>
<<speech "Myra">> "So now it's a forty-minute round trip about olives." <</speech>>
<<speech "$name">> "How long have they been gone?" <</speech>>
<<speech "Myra">> "Two hours." <</speech>>
She lets that sit exactly long enough.
<<speech "Myra">> "They'll come back holding hands. They always do. It's revolting and I've stopped fighting it." <</speech>>
She's quieter than she is in a group — the delivery's the same but she's not performing it for anyone. She holds the loose earbud out sideways.
<<speech "Myra">> "Here. Tell me this is fine so I can be annoyed at you." <</speech>>
You take it. It's slower than you expected, and better.
<<speech "$name">> "It's good." <</speech>>
<<speech "Myra">> "Hm." <</speech>>
<<speech "$name">> "You wanted me to say it was fine." <</speech>>
<<speech "Myra">> "I wanted to be annoyed. I'll manage." <</speech>>
She takes the earbud back and winds the cord round two fingers, which seems to be what she does instead of fidgeting.
<<speech "Myra">> "You're here a lot, you know. More than Blake was at the start." <</speech>>
<<speech "$name">> "Is that a problem?" <</speech>>
<<speech "Myra">> "Opposite. You're the only one who doesn't make me leave the room." <</speech>>
<<speech "Myra">> "Marie sends me out when she wants the place to herself. Very politely. There's a whole speech." <</speech>>
She tips her head back against the sofa cushion.
<<speech "Myra">> "Anyway. They'll be back in twenty minutes and Marie will want to feed everyone, and Blake will say it was her idea, and it wasn't." <</speech>>
<<speech "$name">> "I should probably go before the olives arrive." <</speech>>
<<speech "Myra">> "Don't. If you leave I have to talk to them about olives on my own." <</speech>>
She puts the earbud back in, which is apparently the end of the conversation, and shifts about two inches over to make room on the floor.
<<elseif $meetingTarget is "casey">>
Casey is at the far table with a book she isn't reading and a coat she hasn't taken off. She looks up when you sit down, and her expression does not change.
<<speech "Casey">> "You're Lana's cousin." <</speech>>
<<speech "$name">> "We've met, actually." <</speech>>
<<speech "Casey">> "We've been in the same room. That's different." <</speech>>
She turns a page she hasn't read.
<<speech "Casey">> "She talks about you. At length. I've had entire afternoons of it." <</speech>>
<<speech "$name">> "Sorry." <</speech>>
<<speech "Casey">> "Don't be. It's the only subject where she stops performing." <</speech>>
That lands oddly, and she seems to know it. She closes the book on her finger.
<<speech "Casey">> "Most people want something. I've learned to spot it early — it saves everyone the theatre." <</speech>>
<<speech "$name">> "And what do I want?" <</speech>>
<<speech "Casey">> "That's the irritating part." <</speech>>
She studies you for a moment longer than is comfortable.
<<speech "Casey">> "Lana likes people the way a dog likes people. Indiscriminately, and at volume." <</speech>>
<<speech "Casey">> "But she's not stupid. That's what nobody understands about her." <</speech>>
<<speech "$name">> "You're defending her to me. I'm her family." <</speech>>
<<speech "Casey">> "I'm explaining her to you. It's not the same thing." <</speech>>
She stands, tucks the book under her arm, and pulls her coat straight.
<<speech "Casey">> "She's asked me four times to be civil to you. Consider this the first instalment." <</speech>>
<<speech "$name">> "How many more do I get?" <</speech>>
For a fraction of a second, something moves at the corner of her mouth. It does not become a smile.
<<speech "Casey">> "Three." <</speech>>
She leaves without saying goodbye. At the door she pauses, and does not turn round.
<<speech "Casey">> "She's had a difficult month. Nobody's noticed. You might." <</speech>>
Then she's gone, and the book is still under her arm, and you get the distinct impression she came here to say that and nothing else.
<<elseif $meetingTarget is "harmony">>
You hear her before you see her — Eva's laugh, pitched about a third too high, coming from the front room.
Harmony is in front of the hall mirror with her weight on one hip and her chin up, and she is doing the hair flick. She gets three-quarters of the way through it before she spots you in the doorway.
<<speech "Harmony">> "That wasn't anything." <</speech>>
<<speech "$name">> "It was the hair thing." <</speech>>
<<speech "Harmony">> "It was //not// the hair thing." <</speech>>
<<speech "Harmony">> "Okay it was the hair thing, but she does it //constantly// and nobody ever says anything to her about it, so honestly I think I'm allowed." <</speech>>
She drops onto the arm of the sofa with the exact air of someone who has decided the incident is closed.
<<speech "Harmony">> "She's at the gym. It's the one hour. I have a system." <</speech>>
<<speech "$name">> "A system." <</speech>>
<<speech "Harmony">> "The hour, the mirror, and one song. It's very efficient." <</speech>>
She's already moved on, tapping her heel against the sofa leg.
<<speech "Harmony">> "Did you know Alina's been telling everyone at the gym you never skip? Everyone. Like it's a personality. Kylie thinks it's suspicious." <</speech>>
<<speech "$name">> "Kylie thinks what's suspicious?" <</speech>>
<<speech "Harmony">> "That nobody's ever seen you tired. Her words. I said that's not a crime and she said //everything's// a crime if you look at it long enough, which — fair, actually." <</speech>>
<<speech "$name">> "Should I be worried?" <</speech>>
<<speech "Harmony">> "About Kylie? No. She said the same thing about the postman." <</speech>>
She counts something off on her fingers, apparently to herself, then abandons it.
<<speech "Harmony">> "Also Yulia's failing Adriana's class and hasn't told anyone, and Laila cut her own fringe on Sunday and it's a //situation//, and Maya's mum's out of hospital — that one's good news, that one you can repeat." <</speech>>
<<speech "$name">> "How do you know all that?" <</speech>>
<<speech "Harmony">> "I'm short and I don't talk much, so people forget I'm in the room." <</speech>>
She says it perfectly cheerfully, as though it's a superpower rather than anything else, and swings back off the sofa arm.
<<speech "Harmony">> "Anyway she'll be back at four and she'll want to know why you're here, so have a reason ready." <</speech>>
<<speech "$name">> "I'll say I came to see you." <</speech>>
<<speech "Harmony">> "Don't do //that//, she'll never let it go." <</speech>>
She's already halfway up the stairs, and she leans back round the bannister for one more.
<<speech "Harmony">> "And don't tell her about the mirror." <</speech>>
<<else>>
You introduce yourself. <<print _mc.name>> gives a polite nod.
<</if>>
/* =========================================================================
§ HAREM MANSION
A location the player earns. Once unlocked it behaves like anywhere else:
girls roam here and you can walk in and find them.
WHO ROAMS HERE — G1 Family, G2 Core Support, or anyone at corruption 75+.
Eligible girls have a flat 10% chance of being drawn here over their own
schedule (see haremEligible / HAREM_PULL in JS-Roaming).
WHO YOU CAN INVITE — anyone you have met, at any corruption. The party is
the point of the place: it is the only way to put a specific group of
girls in one room on a day of your choosing.
Police never patrol it, no faction may base here, it is never a
domination goal — noPolice / noFaction / noGoal on its LocationData entry.
========================================================================= */
/* ── WHO CAN FINANCE IT ────────────────────────────────────────────────── */
window.RICH_WOMEN = [
"luna", "jessa", "ember", "nicole", "megan",
/* Autumn is a touring pop star and Momo is an international model; both
keep long-term rooms at the Hotel and can write the cheque. */
"autumn", "momo",
/* v3 */ "india", "kait", "alexis", "alix"
];
/* ── UNLOCK ────────────────────────────────────────────────────────────── */
/* Quinn and Kenna at 75, plus any one rich woman at 75. */
window.canUnlockHarem = function () {
var sv = State.variables;
if (sv.haremUnlocked) return false;
var q = sv.quinn, k = sv.kenna;
if (!q || !k) return false;
if (q.corr < 75 || k.corr < 75) return false;
if (q.arrested || k.arrested) return false;
return window.RICH_WOMEN.some(function (id) {
var c = sv[id];
return c && c.corr >= 75 && !c.arrested;
});
};
/* The financier is locked in the first time she qualifies, so the unlock
scene can name her and she stays named. Same pattern as $contactIntroducer. */
window.getHaremFinancier = function () {
var sv = State.variables;
if (sv.haremFinancier && sv[sv.haremFinancier]) return sv[sv.haremFinancier];
var id = window.RICH_WOMEN.find(function (i) {
var c = sv[i];
return c && c.corr >= 75 && !c.arrested;
});
if (id) sv.haremFinancier = id;
return id ? sv[id] : null;
};
window.unlockHarem = function () {
var sv = State.variables;
window.getHaremFinancier();
sv.haremUnlocked = true;
var loc = (sv.locations || []).find(function (l) { return l.name === "Harem Mansion"; });
if (loc) loc.unlocked = true;
};
/* ── GUEST LIST ────────────────────────────────────────────────────────── */
/* Invitations: anyone you have met. Corruption is irrelevant — bringing an
untouched girl into that house is rather the point. */
window.canAttendHarem = function (id) {
var c = State.variables[id];
if (!c) return false;
if (!c.met) return false;
/* Detained girls are physically in the Lab and cannot attend anything.
Captives, by contrast, are held AT the mansion — assignDailyLocations
pins them there every day once it is unlocked — so excluding them meant
the picker hid women who were standing in the room. They are invitable. */
if (c.arrested) return false;
return true;
};
/* Who will WANDER here on her own, unprompted. Narrower than the guest list. */
window.willRoamToHarem = function (id) {
var c = State.variables[id];
if (!c || !c.met) return false;
if (c.corr >= 75) return true;
/* Was a hardcoded pair of group NAMES, so renaming a group or adding one
with mansion access meant editing code. GROUP_DEFS carries the flag. */
return window.groupHasHaremPull(c.group);
};
window.getHaremEligible = function () {
var sv = State.variables;
return (sv.roster || []).filter(window.canAttendHarem);
};
/* Hard cap 10. Past about 6 the video grid and the mingle log get heavy on
slower machines, so the picker warns rather than blocks. */
window.HAREM_MAX_GUESTS = 10;
window.HAREM_COMFY_LIMIT = 6;
/* ── SUSPICION ─────────────────────────────────────────────────────────── */
/* +5 to +15, scaling with how many people were seen arriving.
Zero if the Police Station has been dominated. */
window.haremPartySuspicion = function (guestCount) {
var sv = State.variables;
var dom = (sv.goalBonuses && sv.goalBonuses.corruptedLocations) || [];
if (dom.indexOf("Police Station") !== -1) return 0;
return Math.min(15, 5 + Math.floor((guestCount || 0) * 1.5));
};
/* ── RUN THE PARTY ─────────────────────────────────────────────────────── */
/* Reuses resolvePartyMingle, exactly as Activity / ClassLecture /
FactionClash / FactionParty do. Returns the log lines to display. */
window.runHaremParty = function () {
var sv = State.variables;
var guests = (sv.haremGuests || []).filter(window.canAttendHarem);
if (!guests.length) return ["Nobody came."];
/* resolvePartyMingle tests isAuthorityPresent(), which matches on
c.location — and nobody is ever *placed* at the mansion, so that check
can never fire here. Park any invited authority figure at the location
for the duration so the witness rule behaves as it does anywhere else,
then put her back. */
var parked = [];
guests.forEach(function (id) {
var c = sv[id];
if (c && c.trait === "authority") {
parked.push([id, c.location]);
c.location = "Harem Mansion";
}
});
var results;
try {
results = window.resolvePartyMingle(guests, "Harem Mansion", "the Harem Mansion party") || [];
} finally {
parked.forEach(function (p) { sv[p[0]].location = p[1]; });
}
var susp = window.haremPartySuspicion(guests.length);
if (susp > 0) {
/* "party" so Discreet Gatherings can zero it. */
window.addSuspicion(susp, "party");
results.push('<span style="color:#ff8844">Cars on the drive all evening. +' +
susp + ' suspicion.</span>');
} else {
results.push('<span style="color:#44ff88">The police have no interest in this address.</span>');
}
sv.haremPartyToday = true;
return results;
};<<nobr>>
<<set _fin = window.getHaremFinancier()>>
<<set _fid = _fin ? _fin.var : "luna">>
<<set _fname = _fin ? _fin.name : "your financier">>
<</nobr>>
<div style="max-width:680px; margin:0 auto; padding:0 20px 40px;">
<div style="text-align:center; border-bottom:2px solid #9c27b0; padding-bottom:12px; margin-bottom:22px;">
<h1 style="margin:0; color:#bd59ff;">🍾 The Empty House</h1>
<div style="color:#777; font-size:0.85em; font-style:italic; margin-top:4px;">
Eight bedrooms. A coach house. Nobody's name on it in years.
</div>
</div>
<div class="narrative-box">
It starts in the night, and it does not start as an idea.
You are half asleep when it turns over in you — not pain, not hunger, something worse, a slow flexing of attention like an animal waking up and finding the box it is in too small. It has been quiet for weeks. It is not quiet now.
//Every room you take me into belongs to somebody else.//
You lie there in the dark of a rented room with damp in one corner and listen to it think.
//A cafeteria. A poolside. A shop floor with a bell on the door. You bring them to me in other people's buildings and we are always, always about to be interrupted.//
You think, at it rather than to it, that nobody has interrupted anything yet.
//Not yet. And I spend the whole of it listening for the door instead of enjoying what I am doing. I want somewhere with no door to listen to.//
By morning it is not asking. It is simply directing your attention, the way it directs your eyes to a throat or a wrist — you find yourself thinking about the estate agency before you have decided to, and the thought has a shape to it that is not yours.
You go. You don't remember choosing to.
Kenna and Quinn look up when the bell goes and neither of them seems surprised to see you, which is its own kind of answer.
<<speech "$name">>"The empty place out past the mansion. Get it for me."<</speech>>
Quinn is already moving to the screen. Kenna has the file out of the drawer before you finish the sentence, and it is not a new file — it is soft at the corners, handled, opened and closed a hundred times over months.
<<speech "Kenna">>"I've had it ready since before you knew you wanted it."<</speech>>
<<speech "$name">>"Then you already know what I'm going to say next."<</speech>>
<<speech "Kenna">>"You want it clean. No name that leads back to you, nothing on the register anybody would think to look at."<</speech>>
<<speech "$name">>"Can you do that?"<</speech>>
<<speech "Kenna">>"I've been doing that for people in this town since before Quinn could drive. The difference is they were paying me."<</speech>>
The photographs go up on the screen — the frontage, eight dark windows, the grounds with the treeline running the whole way round, the coach house with its own door onto a lane nobody uses. Something behind your eyes goes very still, the way it does when a girl walks into a room.
//There. That one. Look at how far it is from anything.//
<<speech "Quinn">>"It's dead stock. The last owner died without anybody to leave it to and it has sat there ever since — two price drops, no viewings in over a year."<</speech>>
<<speech "Kenna">>"And it needs everything. Roof, wiring, half the plaster. Whoever takes it is buying a building site with good bones and paying for the privilege."<</speech>>
<<speech "Quinn">>"Which is the only reason it's still on our books at a price anybody could reach. Nobody in this town wants eight bedrooms badly enough to fund a year of work first."<</speech>>
<<speech "$name">>"I need eight bedrooms."<</speech>>
<<speech "Quinn">>(without a flicker) "I know. That's why I've been putting it in front of you since the first day you came in here about a student let."<</speech>>
The money is the only real problem and it is not a problem for long. <<print _fname>> arrives inside the hour, having been telephoned by Kenna without anybody consulting you, and she does not ask what the house is for. She reads two pages, turns to the back, and signs.
<<speech _fid>>"It's done. The money's mine and nobody audits me."<</speech>>
<<speech "$name">>"You didn't ask what I want it for."<</speech>>
<<speech _fid>>"No."<</speech>>
She puts the pen down and looks at you and there is nothing in her face but a sort of quiet appetite, patient and entirely willing.
<<speech _fid>>"I assume you'll tell me when you want me there."<</speech>>
The keys are in a brown envelope with the address written on it in somebody's handwriting from years ago. Kenna slides them across the desk with two fingers and does not let go straight away.
<<speech "Kenna">>"Nobody overlooks it. There's a lane in and the lane goes nowhere else. Whatever happens up there, happens up there."<</speech>>
<<speech "$name">>"That's exactly what I wanted to hear."<</speech>>
<<speech "Kenna">>"I know. I've known for months. I've just been waiting for you to come and ask."<</speech>>
You drive out that afternoon. The lane is longer than it looks on the map and the treeline closes over it about halfway along, and then the house — grey, enormous, every window dark, standing in its own silence like something holding its breath.
The key turns, badly, and then all at once. The hall smells of dust sheets and cold plaster and years of nobody. There is a stain across the ceiling where the roof has been letting the weather in, and the light switch by the door does nothing at all.
None of that matters to the thing in your head, which is not looking at the ceiling.
And the thing inside you unfolds, all at once, filling you up to the fingertips — no words in it now, just a long low satisfaction that goes on and on, the way a cat settles into a patch of sun.
//Bring them here. All of them. Nobody is coming up that lane.//
</div>
<div style="background:#0d0d1a; border:1px solid #6a0dad; border-radius:8px; padding:14px; margin:22px 0; font-size:0.9em; color:#ccc;">
<div style="color:#bd59ff; font-weight:bold; margin-bottom:8px;">🍾 Harem Mansion unlocked</div>
<ul style="margin:0; padding-left:18px; line-height:1.7;">
<li>It is at the top of your map, and it is yours — dust sheets, bad roof and all.</li>
<li><b>Family</b>, <b>Core Support</b> and anyone at corruption <b>75+</b> will start turning up here on their own — a 10% pull against their usual day.</li>
<li><b>Host a Party</b> is always available, and you may invite <b>anyone you have met</b>, at any corruption. Everywhere else you get whoever happens to be in the building.</li>
<li>One party per day, and it costs you the day's activity.</li>
<li>Cars on the drive get noticed — <b>+5 to +15 suspicion</b>, unless the Police Station is yours.</li>
</ul>
</div>
<div style="text-align:center; margin-top:22px;">
<<button "Take the keys">><<goto "DayStart">><</button>>
</div>
</div><<nobr>>
/* ─────────────────────────────────────────────────────────────────────────
Whole passage wrapped in nobr — same fix as Factions. Otherwise every
newline in the markup renders as a line break and the grid is pushed
apart by ~80 of them. All spacing comes from CSS.
───────────────────────────────────────────────────────────────────────── */
<<set _elig = window.getHaremEligible()>>
<<set _max = window.HAREM_MAX_GUESTS>>
<<set _comfy = window.HAREM_COMFY_LIMIT>>
/* Was a fifth hardcoded copy of the group names. $groups is derived from the
roster at StoryInit and already carries them in definition order, with any
custom (mod) group appended, so read the order from there. */
<<set _groupOrder = $groups.map(g => g.name)>>
<div id="hp-root">
<style>
/* Scoped. The global `.loc-btn-wrapper button { width:100% }` would stretch
every tile across the row, so this passage does not use that class. */
#hp-root { max-width:880px; margin:0 auto; padding:0 16px 40px; }
#hp-root .hp-tile button { width:92px !important; height:128px !important; margin:0 !important; padding:0 !important; border:2px solid #2a2a2a; border-radius:6px; background-size:cover; background-position:center top; background-repeat:no-repeat; cursor:pointer; position:relative; overflow:hidden; font-size:0 !important; line-height:0 !important; transition:border-color 0.12s, transform 0.12s; }
#hp-root .hp-tile button:hover { border-color:#bd59ff; transform:translateY(-2px); }
#hp-root .hp-tile.on button { border-color:#44ff88; box-shadow:0 0 9px rgba(68,255,136,0.45); }
#hp-root .hp-cell { position:relative; width:92px; }
#hp-root .hp-grid { display:flex; flex-wrap:wrap; gap:8px; }
#hp-root .hp-name { position:absolute; left:0; right:0; bottom:0; background:linear-gradient(transparent, rgba(0,0,0,0.92) 55%); color:#ddd; font-size:0.72em; text-align:center; padding:12px 2px 3px; pointer-events:none; border-radius:0 0 4px 4px; line-height:1.2; }
#hp-root .hp-corr { display:block; font-size:0.85em; color:#9c7ab0; }
#hp-root .hp-tick { position:absolute; top:4px; right:4px; width:19px; height:19px; border-radius:50%; background:#44ff88; color:#04220f; font-size:0.78em; font-weight:bold; display:flex; align-items:center; justify-content:center; pointer-events:none; }
#hp-root .hp-hdr { color:#bd59ff; font-size:0.72em; font-weight:bold; text-transform:uppercase; letter-spacing:0.1em; border-bottom:1px solid #2a1a3a; padding-bottom:3px; margin:14px 0 8px; }
#hp-root .hp-go button { width:auto !important; padding:5px 18px !important; font-size:0.92em !important; margin:0 !important; }
</style>
<div style="text-align:center; border-bottom:2px solid #9c27b0; padding-bottom:8px; margin-bottom:8px;"><h1 style="margin:0; color:#bd59ff;">🍾 Guest List</h1></div>
<div style="text-align:center; color:#888; font-size:0.84em;">Anyone you have met — <b style="color:#bd59ff;"><<print _elig.length>></b> of <<print $roster.length>> available. Corruption doesn't matter.</div>
<div style="text-align:center; color:#777; font-size:0.76em; font-style:italic; margin-bottom:8px;">Up to <<print _max>> guests. More than <<print _comfy>> may run slowly on some machines.</div>
<<if _elig.some(id => State.variables[id].captive)>><div style="text-align:center; color:#a06a6a; font-size:0.76em; margin-bottom:8px;">🔒 marks a captive — she is already in the house.</div><</if>>
<div id="hp-count" style="text-align:center; color:#bd59ff; font-weight:bold; font-size:0.9em; margin-bottom:14px; min-height:2.4em;">0 / <<print _max>> invited</div>
<<for _g range _groupOrder>><<capture _g>><<set _inGroup = _elig.filter(id => window.getGroupLabel(State.variables[id].group) === _g)>><<if _inGroup.length > 0>><div class="hp-hdr"><<print _g>></div><div class="hp-grid"><<for _id range _inGroup>><<capture _id>><<set _c = State.variables[_id]>><div class="hp-cell"><span @class="'hp-tile' + ($haremGuests.includes(_id) ? ' on' : '')" @id="'hp-t-' + _id"><<button "">><<if $haremGuests.includes(_id)>><<run $haremGuests.delete(_id)>><<run $("#hp-t-" + _id).removeClass("on")>><<run $("#hp-k-" + _id).hide()>><<elseif $haremGuests.length lt _max>><<run $haremGuests.push(_id)>><<run $("#hp-t-" + _id).addClass("on")>><<run $("#hp-k-" + _id).show()>><</if>><<replace "#hp-count">><<print $haremGuests.length>> / <<print _max>> invited<<if $haremGuests.length gt 0>><br><span style="color:#999; font-weight:normal; font-size:0.9em;"><<print $haremGuests.map(g => State.variables[g].name).join(", ")>></span><</if>><<if $haremGuests.length gt _comfy>><br><span style="color:#ff8844; font-weight:normal; font-size:0.85em;">⚠ A party this size may run slowly.</span><</if>><</replace>><<replace "#hp-go">><<if $haremGuests.length gt 0>><span class="hp-go"><<button "Start the Party">><<goto "HaremPartyScene">><</button>></span><<else>><span style="color:#555; font-style:italic;">Invite somebody first.</span><</if>><</replace>><</button>></span><span @id="'hp-k-' + _id" class="hp-tick" @style="'display:' + ($haremGuests.includes(_id) ? 'flex' : 'none') + ';'">✓</span><span class="hp-name"><<print _c.name>><span class="hp-corr"><<print _c.corr>>%<<if _c.infected>> ☣<</if>><<if _c.captive>> 🔒<</if>></span></span></div><</capture>><</for>></div><</if>><</capture>><</for>>
<div id="hp-go" style="text-align:center; margin-top:26px;"><span style="color:#555; font-style:italic;">Invite somebody first.</span></div>
<div style="text-align:center; margin-top:14px;"><span class="hp-go"><<button "← Back">><<set $haremGuests = []>><<goto "TownHub">><</button>></span></div>
</div>
<</nobr>>
<<script>>
/* Paint the portraits onto the buttons themselves — a background on the
wrapper would sit behind the button and never show. */
(function () {
var sv = State.variables;
setTimeout(function () {
$("#hp-root .hp-tile").each(function () {
var id = $(this).attr("id");
if (!id) return;
var c = sv[id.replace("hp-t-", "")];
if (!c) return;
$(this).find("button").css("background-image",
"url('" + window.getPortraitPath(c.name) + "')");
});
}, 0);
})();
<</script>><<nobr>>
<<set _actLoc = "Harem Mansion">>
<<set _actName = "🍾 Harem Party">>
<<set _attendees = $haremGuests.filter(id => window.canAttendHarem(id))>>
<<set _results = window.runHaremParty()>>
<<set _corrupt = []>>
<<for _id range _attendees>>
<<if State.variables[_id].corr >= 25>><<run _corrupt.push(_id)>><</if>>
<</for>>
/* Limit video list to girlsPerScene */
<<set _videoList = _attendees.filter(id => State.variables[id].corr >= 25).slice(0, ($settings && $settings.girlsPerScene) ? $settings.girlsPerScene : 4)>>
<</nobr>>
<div style="text-align:center; margin-bottom:20px; border-bottom:2px solid #9c27b0; padding-bottom:10px;">
<h1 style="margin:0; color:#bd59ff;"><<print _actName>></h1>
<div style="color:#aaa; font-size:0.9em; margin-top:4px;">
<<print _actLoc>> · Parasites: <span style="color:#bd59ff; font-weight:bold;">$parasite</span>
· Infected: <span style="color:<<if window.hivemindFull()>>#ff5555<<else>>#bd59ff<</if>>;">
<<print window.getHivemindLoad()>> / <<print $hivemindCap>>
</span>
</div>
</div>
<<if _videoList.length > 0>>
<div style="background:#000; padding:10px; border:1px solid #333; border-radius:8px; margin-bottom:20px;">
<<GroupVideos _videoList>>
</div>
<<else>>
<div style="text-align:center; color:#555; font-style:italic; padding:15px; background:#111; border-radius:6px; margin-bottom:20px;">
Nothing out of the ordinary... yet.
</div>
<</if>>
<<if _results.length > 0>>
<div style="background:#1a1a1a; border:1px solid #9c27b0; border-radius:6px; padding:12px; margin-bottom:20px;">
<strong style="color:#bd59ff; font-size:0.9em; text-transform:uppercase; display:block; margin-bottom:8px;">Events</strong>
<ul style="margin:0; padding-left:18px; color:#ccc; font-size:0.9em;">
<<for _msg range _results>><li style="margin-bottom:3px;"><<print _msg>></li><</for>>
</ul>
</div>
<</if>>
<div style="display:flex; flex-wrap:wrap; gap:10px; justify-content:flex-start; margin-bottom:20px;">
<<for _id range _attendees>>
<<set _char = State.variables[_id]>>
<<capture _id>>
<<set _girlCap = window.getCorrCap ? window.getCorrCap(_id) : 25>>
<<set _atCap = _char.infected && _char.corr >= _girlCap && _char.corr < 100>>
<div style="text-align:center; width:140px;">
<<if _char.met>>
<<set _img = window.getEventImagePath(_char.name)>>
<div @style="'width:140px; height:210px; background-image:url(' + _img + '); background-size:cover; background-position:center top; border-radius:6px; position:relative; border:2px solid ' + (_atCap ? '#bd59ff' : 'transparent') + ';'">
<div class="loc-bar-container">
<div class="loc-bar-fill" @style="'width:' + _char.corr + '%'"></div>
</div>
<<if _atCap>>
<div style="position:absolute; top:3px; right:3px; background:#bd59ff; color:#fff; font-size:0.58em; font-weight:bold; padding:2px 4px; border-radius:3px;">CAP</div>
<</if>>
</div>
<div style="font-size:0.85em; font-weight:bold; color:#ccc; margin-top:4px;"><<charLink _id>></div>
<div style="font-size:0.75em; margin-top:2px;">
<<if _char.breed>><span style="color:#ff5959;">♥ Bred</span>
<<elseif _char.infected>><span style="color:#bd59ff;">☣ Infected</span>
<<else>><span style="color:#444;">Healthy</span>
<</if>>
</div>
<<else>>
<div style="width:140px; height:210px; background:#111; border-radius:6px; display:flex; align-items:center; justify-content:center; border:1px solid #222;">
<span style="font-size:3em; color:#444;">?</span>
</div>
<div style="font-size:0.85em; color:#444; margin-top:4px;">???</div>
<</if>>
</div>
<</capture>>
<</for>>
</div>
/* ── BRED CHECK ── */
<<set _newlyBred = []>>
<<for _bid range _attendees>>
<<set _bc = State.variables[_bid]>>
/* Breeding: corruption 75 or more. The old rule ALSO demanded she be at her
personal cap, which made breeding impossible for most of the late game —
once you bought Universal Threshold III (or broke her cap) the ceiling was
100, so a devoted girl at 75, 80 or 90 could never be bred. Only a girl
sitting exactly at her cap qualified, which is why it fired sometimes and
not others. 75 is the Devoted threshold and is the intended gate. */
<<if _bc.corr >= 75 and !_bc.breed>>
<<set State.variables[_bid].breed = true>>
<<run _newlyBred.push(_bc.name)>>
<</if>>
<</for>>
<<if _newlyBred.length > 0>>
<div style="background:#1a0010; border:1px solid #ff5959; border-radius:6px; padding:12px; margin-bottom:20px; text-align:center;">
<strong style="color:#ff5959; font-size:0.95em; display:block; margin-bottom:8px;">♥ Bred This Activity</strong>
<<for _bn range _newlyBred>>
<div style="color:#ff8888; font-size:0.9em; margin-bottom:2px;"><<print _bn>> has been bred.</div>
<</for>>
</div>
<</if>>
<div style="margin-top:24px; text-align:center; display:flex; gap:12px; justify-content:center; flex-wrap:wrap;">
<<button "Sleep">><<set $haremGuests = []>><<goto "DayEnd">><</button>>
<<button "Back to the Hub">><<set $haremGuests = []>><<goto "TownHub">><</button>>
</div>/* =========================================================================
§ 9. FACTION SYSTEM — DAILY EVENTS & THE NIGHTLY PASS
-------------------------------------------------------------------------
Part 3 of 4. Split out of the original JS-Factions, which had reached
2,000+ lines. Load order in StoryInit matters:
JS-Factions-Core -> JS-Factions-Events ->
JS-Factions-Clash -> JS-Factions-Directives
Each is eval'd separately, so nothing may rely on another file's
top-level const. Shared tuning values live on window.FACTION_CFG in
Core and are read from there everywhere else.
========================================================================= */
/* Aliases for the shared tuning values defined in JS-Factions-Core. */
var FACTION_STRUCTURAL_COOLDOWN = window.FACTION_CFG.STRUCTURAL_COOLDOWN;
var FACTION_RARE_COOLDOWN = window.FACTION_CFG.RARE_COOLDOWN;
var FACTION_PROTECTION_WINDOW = window.FACTION_CFG.PROTECTION_WINDOW;
var FACTION_PROTECTION_MIN = window.FACTION_CFG.PROTECTION_MIN;
var FACTION_HISTORY_DAYS = window.FACTION_CFG.HISTORY_DAYS;
var FACTION_HOME_MIN_VISITS = window.FACTION_CFG.HOME_MIN_VISITS;
var TERRITORY_MAX_PER_LOC = window.FACTION_CFG.TERRITORY_MAX;
var TERRITORY_CLASH_AFTER = window.FACTION_CFG.TERRITORY_CLASH;
window.updateTerritoryConflicts = function(log) {
/* Territory conflicts replaced by new clash system — no-op */
};
/* ── PLAYER INFLUENCE TICK ───────────────────────────────────────────────
Increases when Player was at the same location as faction members today.
────────────────────────────────────────────────────────────────────── */
window.tickplayerInfluence = function(faction) {
let sv = State.variables;
let natLoc = sv.currentLocation;
if (!natLoc) return;
let present = faction.members.some(function(id) {
let c = sv[id];
return c && c.location === natLoc;
});
if (present) {
faction.playerInfluence = Math.min(100, (faction.playerInfluence || 0) + 2);
}
};
/* ── GROWTH ──────────────────────────────────────────────────────────────
Gated: lastStructuralChange + FACTION_STRUCTURAL_COOLDOWN
Stability gate: > 40
────────────────────────────────────────────────────────────────────── */
window.checkFactionGrowth = function(faction, log) {
let sv = State.variables;
let day = sv.day;
/* BUGFIX: the Recruitment directive set faction.pendingRecruitment = true
and nothing ever read it, so the directive silently did nothing. It is
now honoured here — a forced recruit skips the stability floor, the
structural cooldown and the 15% roll, but still respects max size. */
let forced = faction.pendingRecruitment === true;
if (faction.members.length >= (sv.settings && sv.settings.factionMaxSize ? sv.settings.factionMaxSize : 7)) {
faction.pendingRecruitment = false;
return;
}
if (!forced) {
if ((faction.stability || 50) <= 40) return;
if ((day - (faction.lastStructuralChange || 0)) < FACTION_STRUCTURAL_COOLDOWN) return;
}
/* Candidates: girls at the same location as any member, not in any faction */
let memberLocs = [...new Set(faction.members.map(id => sv[id] ? sv[id].location : null).filter(Boolean))];
let candidates = [];
memberLocs.forEach(function(loc) {
sv.roster.forEach(function(id) {
let c = sv[id];
if (!c || c.arrested || c.location !== loc) return;
/* A captive is unaffiliated by definition — makeCaptive strips her
from her faction — and once the mansion is unlocked she is parked
there every day alongside anyone else who roams in. Without this
guard a faction meeting at the mansion would happily "recruit"
a girl who is locked in the basement. */
if (c.captive) return;
if (faction.members.includes(id)) return;
if (sv.factions.some(f => f.members.includes(id))) return;
candidates.push(id);
});
});
if (!candidates.length) return;
if (!forced && Math.random() >= 0.15) return;
let recruit = candidates[Math.floor(Math.random() * candidates.length)];
faction.members.push(recruit);
faction.pendingRecruitment = false;
faction.members.forEach(function(id) {
let c = sv[id];
if (!c.connections) c.connections = [];
if (id !== recruit && !c.connections.includes(recruit)) c.connections.push(recruit);
if (id !== recruit && !sv[recruit].connections.includes(id)) sv[recruit].connections.push(id);
});
faction.lastStructuralChange = day;
let recruitChar = sv[recruit];
/* Name her whenever she is actually known. factionLog picks the partial
string on visibility 1 — which only means SOMEBODY in the faction is
unmet, not that this recruit is. Anonymising a girl the player knows
reads as a bug. Decide per-subject instead. */
window.factionLog(log, faction,
`<span style="color:#44aaff">★ <b>${recruitChar.name}</b> joined <b>${window.factionDisplayName(faction)}</b>.</span>`,
recruitChar.met
? `<span style="color:#44aaff">★ <b>${recruitChar.name}</b> joined <b>${window.factionDisplayName(faction)}</b>.</span>`
: `<span style="color:#44aaff">★ Someone new joined <b>${window.factionDisplayName(faction)}</b>.</span>`
);
};
/* ── EXPULSION ───────────────────────────────────────────────────────────
Gated: lastStructuralChange + FACTION_STRUCTURAL_COOLDOWN
Stability gate: < 50
────────────────────────────────────────────────────────────────────── */
window.checkFactionExpulsion = function(faction, log) {
let sv = State.variables;
let day = sv.day;
if ((faction.stability || 50) >= 50) return;
if ((day - (faction.lastStructuralChange || 0)) < FACTION_STRUCTURAL_COOLDOWN) return;
if (faction.members.length <= 2) return;
let weak = faction.members
.filter(id => id !== faction.leader)
.filter(id => sv[id] && (faction.corruption - sv[id].corr) >= 30);
if (!weak.length || Math.random() >= 0.15) return;
let expelled = weak[Math.floor(Math.random() * weak.length)];
faction.members = faction.members.filter(id => id !== expelled);
faction.lastStructuralChange = day;
let expChar = sv[expelled];
window.factionLog(log, faction,
`<span style="color:#ff8844">★ <b>${expChar.name}</b> was pushed out of <b>${window.factionDisplayName(faction)}</b>.</span>`,
expChar.met
? `<span style="color:#ff8844">★ <b>${expChar.name}</b> was pushed out of <b>${window.factionDisplayName(faction)}</b>.</span>`
: `<span style="color:#ff8844">★ A member was pushed out of <b>${window.factionDisplayName(faction)}</b>.</span>`
);
};
/* ── LEADER SHIFT ────────────────────────────────────────────────────────
If leader corr < faction average by 20+, leadership passes to
the highest-corr member. Gated by structural cooldown.
────────────────────────────────────────────────────────────────────── */
window.checkFactionLeaderShift = function(faction, log) {
let sv = State.variables;
let day = sv.day;
if ((day - (faction.lastStructuralChange || 0)) < FACTION_STRUCTURAL_COOLDOWN) return;
let leader = sv[faction.leader];
if (!leader) return;
if ((faction.corruption - leader.corr) < 20) return;
/* Highest-corruption non-leader. An unknown girl may lead — that is fine,
the faction simply stays unknown until you meet somebody in it. */
let newLeaderId = null, bestCorr = -1;
faction.members.forEach(function(id) {
if (id === faction.leader) return;
let c = sv[id];
if (!c || c.captive) return;
if (c.corr > bestCorr) { bestCorr = c.corr; newLeaderId = id; }
});
if (!newLeaderId) return;
let oldName = leader.name;
let newChar = sv[newLeaderId];
faction.leader = newLeaderId;
faction.name = newChar.name + "'s Friends";
faction.lastStructuralChange = day;
/* The outgoing leader is met by definition (visibility > 0 requires it).
Only the incoming one may be unknown. */
window.factionLog(log, faction,
`<span style="color:#aaaaff">★ Leadership of <b>${window.factionDisplayName(faction)}</b> shifted from <b>${oldName}</b> to <b>${newChar.name}</b>.</span>`,
newChar.met
? `<span style="color:#aaaaff">★ Leadership of <b>${window.factionDisplayName(faction)}</b> shifted from <b>${oldName}</b> to <b>${newChar.name}</b>.</span>`
: `<span style="color:#aaaaff">★ Leadership of <b>${window.factionDisplayName(faction)}</b> passed to someone you haven't met.</span>`
);
};
/* ── MERGE ───────────────────────────────────────────────────────────────
Rare event. Both factions must have stability > 60. 14-day cooldown.
────────────────────────────────────────────────────────────────────── */
window.checkFactionMerge = function(log) {
let sv = State.variables;
let day = sv.day;
if (!sv.factions || sv.factions.length < 2) return;
for (let i = 0; i < sv.factions.length; i++) {
for (let j = i + 1; j < sv.factions.length; j++) {
let f1 = sv.factions[i], f2 = sv.factions[j];
if ((f1.stability || 50) < 60 || (f2.stability || 50) < 60) continue;
if ((day - (f1.lastStructuralChange || 0)) < FACTION_RARE_COOLDOWN) continue;
if ((day - (f2.lastStructuralChange || 0)) < FACTION_RARE_COOLDOWN) continue;
if (Math.random() > 0.05) continue;
let combined = [...new Set([...f1.members, ...f2.members])];
if (combined.length > 7) continue;
/* Require connection overlap */
let overlap = f1.members.filter(id =>
f2.members.some(id2 => sv[id] && sv[id].connections && sv[id].connections.includes(id2))
);
if (overlap.length < 2) continue;
let [base, absorb] = f1.members.length >= f2.members.length ? [f1, f2] : [f2, f1];
base.members = combined;
base.members.forEach(function(id1) {
base.members.forEach(function(id2) {
if (id1 !== id2 && sv[id1] && !sv[id1].connections.includes(id2))
sv[id1].connections.push(id2);
});
});
base.stability = Math.floor(((base.stability || 50) + (absorb.stability || 50)) / 2);
base.lastStructuralChange = day;
base.name = sv[base.leader].name + "'s Friends";
sv.factions = sv.factions.filter(f => f.id !== absorb.id);
/* Always log merges */
log.push(`<span style="color:#44aaff">★ <b>${absorb.name}</b> merged into <b>${base.name}</b>.</span>`);
return;
}
}
};
/* ── SPLIT ───────────────────────────────────────────────────────────────
Rare event. Stability must be < 30. 14-day cooldown.
────────────────────────────────────────────────────────────────────── */
window.checkFactionSplit = function(log) {
let sv = State.variables;
let day = sv.day;
if (!sv.factions) return;
sv.factions.forEach(function(faction) {
if (faction.members.length < 5) return;
if ((faction.stability || 50) >= 30) return;
if ((day - (faction.lastStructuralChange || 0)) < FACTION_RARE_COOLDOWN) return;
let rivals = faction.members.filter(id =>
id !== faction.leader && sv[id] && sv[id].corr >= 40
);
if (!rivals.length || Math.random() >= 0.10) return;
let rivalId = rivals[Math.floor(Math.random() * rivals.length)];
let rivalName = sv[rivalId] ? sv[rivalId].name : "Someone";
let defectors = faction.members.filter(id => id !== faction.leader && id !== rivalId);
let followerCount = Math.min(Math.floor(Math.random() * 2) + 2, defectors.length);
let followers = defectors.sort(() => 0.5 - Math.random()).slice(0, followerCount);
let newFaction = {
id: window.allocFactionId(),
leader: rivalId,
members: [rivalId, ...followers],
name: rivalName + "'s Splinter Group",
corruption: 0,
stability: 40,
formed: day,
lastStructuralChange: day,
lastEvent: day,
homeLocation: null,
locationHistory: [],
stance: "neutral",
rivalOf: [faction.id],
playerInfluence: 0,
directive: null
};
newFaction.corruption = Math.floor(
newFaction.members.reduce((s, id) => s + (sv[id] ? sv[id].corr : 0), 0) / newFaction.members.length
);
newFaction.members.forEach(function(id1) {
newFaction.members.forEach(function(id2) {
if (id1 !== id2 && sv[id1] && !sv[id1].connections.includes(id2))
sv[id1].connections.push(id2);
});
});
faction.members = faction.members.filter(id => !newFaction.members.includes(id));
faction.lastStructuralChange = day;
if (!faction.rivalOf) faction.rivalOf = [];
if (!faction.rivalOf.includes(newFaction.id)) faction.rivalOf.push(newFaction.id);
sv.factions.push(newFaction);
/* Always log splits */
log.push(`<span style="color:#ffcc00">⚠ SPLIT: <b>${rivalName}</b> broke away from <b>${window.factionDisplayName(faction)}</b> with ${followers.length} others!</span>`);
});
};
/* ── DISBAND ─────────────────────────────────────────────────────────────
Stability must be < 20. 14-day cooldown. 7-day protection window.
────────────────────────────────────────────────────────────────────── */
window.checkFactionDisband = function(log) {
let sv = State.variables;
let day = sv.day;
if (!sv.factions) return;
sv.factions = sv.factions.filter(function(faction) {
/* Always disband if only 1 member */
if (faction.members.length <= 1) {
window.factionLog(log, faction,
`<span style="color:#666">★ <b>${window.factionDisplayNameCap(faction)}</b> dissolved (too few members).</span>`,
`<span style="color:#666">★ <b>${window.factionDisplayNameCap(faction)}</b> dissolved (too few members).</span>`
);
return false;
}
let age = day - (faction.formed || 0);
if (age < FACTION_PROTECTION_WINDOW) return true;
if ((faction.stability || 50) >= 20) return true;
if ((day - (faction.lastStructuralChange || 0)) < FACTION_RARE_COOLDOWN) return true;
if (Math.random() >= 0.15) return true;
/* Always log disbands */
log.push(`<span style="color:#ff4444">★ <b>${window.factionDisplayNameCap(faction)}</b> collapsed due to internal instability.</span>`);
return false;
});
};
/* ── PARTY ───────────────────────────────────────────────────────────────
7-day cooldown via lastEvent. Only if stability > 30.
BUGFIX: a second, divergent copy of this function lived in JS-Nests. That
copy supported the Force Party directive (faction.pendingRecruitment ===
"party") but dropped sv.pendingPartiesDay, which TownHub needs to clear
stale invites. JS-Factions loads after JS-Nests, so this copy always won
and the Nests one was dead — meaning Force Party's flag was never read.
The two are now merged here and the JS-Nests duplicate is deleted.
forceParty bypasses the cooldown, the stability floor and the dice roll:
the player paid a directive for it, so it must actually happen.
────────────────────────────────────────────────────────────────────── */
window.checkFactionParty = function(faction, log) {
let sv = State.variables;
let day = sv.day;
let leader = sv[faction.leader];
/* If the leader hasn't been met, the player gets no invite/log entry */
if (!leader || !leader.met) return;
/* Force Party directive — set by the directive, honoured here */
let forceParty = faction.pendingParty === true;
if (!faction.lastEvent) faction.lastEvent = 0;
if (!forceParty) {
if (day - faction.lastEvent < 7) return;
if ((faction.stability || 50) < 30) return;
if (Math.random() >= 0.15) return;
}
faction.lastEvent = day;
faction.pendingParty = false;
if (!sv.pendingParties) sv.pendingParties = [];
if (!sv.pendingParties.includes(faction.id)) {
sv.pendingParties.push(faction.id);
}
/* Always refresh — TownHub clears the list once $day passes this */
sv.pendingPartiesDay = day;
/* Visibility is already > 0 here, which means the leader IS met — so the
faction's name is known to the player and there is no reason to fall
back to "a group". Only the unnamed-member roster is uncertain. */
window.factionLog(log, faction,
`<span style="color:#bd59ff">★ <b>${window.factionDisplayNameCap(faction)}</b> is throwing a party tonight! You can attend tomorrow.</span>`,
`<span style="color:#bd59ff">★ <b>${window.factionDisplayNameCap(faction)}</b> is throwing a party tonight! You can attend tomorrow.</span>`
);
};
/* ── FORMATION ───────────────────────────────────────────────────────────
Only forms between girls who already share a connection.
Minimum 3% chance (down from 15%). No formation if either girl is
already in a faction.
────────────────────────────────────────────────────────────────────── */
window.checkFactionFormation = function(log) {
let sv = State.variables;
let roster = sv.roster;
if (!sv.factions) sv.factions = [];
/* Build loc → eligible girls map */
let locMap = {};
roster.forEach(function(id) {
let c = sv[id];
if (!c || c.arrested) return;
if (sv.factions.some(f => f.members.includes(id))) return;
if (c.captive) return; /* held — she forms nothing */
if (!c.location) return;
if (!locMap[c.location]) locMap[c.location] = [];
locMap[c.location].push(id);
});
Object.keys(locMap).forEach(function(loc) {
let chars = locMap[loc];
if (chars.length < 2 || Math.random() > 0.03) return;
/* Require at least one connection pair among those present */
let hasPair = chars.some(function(id1) {
return chars.some(function(id2) {
return id1 !== id2 && sv[id1] && sv[id1].connections &&
sv[id1].connections.includes(id2);
});
});
if (!hasPair) return;
let size = Math.min(Math.floor(Math.random() * 3) + 2, chars.length);
let members = chars.sort(() => Math.random() - 0.5).slice(0, size);
let leader = members.reduce((a, b) => (sv[a] ? sv[a].corr : 0) >= (sv[b] ? sv[b].corr : 0) ? a : b);
let faction = {
id: window.allocFactionId(),
leader: leader,
members: members,
name: (sv[leader] ? sv[leader].name : "Unknown") + "'s Friends",
corruption: Math.floor(members.reduce((s, id) => s + (sv[id] ? sv[id].corr : 0), 0) / members.length),
stability: 50,
formed: sv.day,
lastStructuralChange: sv.day,
lastEvent: sv.day,
homeLocation: null,
locationHistory: [],
stance: "neutral",
rivalOf: [],
playerInfluence: 0,
directive: null
};
members.forEach(function(id1) {
let c1 = sv[id1];
if (!c1.connections) c1.connections = [];
members.forEach(function(id2) {
if (id1 !== id2 && !c1.connections.includes(id2)) c1.connections.push(id2);
});
});
sv.factions.push(faction);
window.factionLog(log, faction,
`<span style="color:#44aaff">★ <b>${window.factionDisplayNameCap(faction)}</b> formed with ${members.length} members.</span>`,
`<span style="color:#44aaff">★ <b>${window.factionDisplayNameCap(faction)}</b> formed with ${members.length} members.</span>`
);
});
};
/* ── RECRUIT CHANCE ──────────────────────────────────────────────────────
Used by both AI growth and Player's Recruit directive.
Returns a 0-1 probability.
────────────────────────────────────────────────────────────────────── */
window.calculateRecruitChance = function(factionId, prospectId) {
let sv = State.variables;
let faction = sv.factions.find(f => f.id === factionId);
let prospect = sv[prospectId];
if (!faction || !prospect) return 0;
let chance = 0.20;
/* Co-location history bonus: +5% per day shared with any member, capped +30% */
let sharedDays = 0;
if (faction.locationHistory) {
faction.locationHistory.forEach(function(e) {
if (sv[prospectId] && sv[prospectId].location === e.loc) sharedDays++;
});
}
chance += Math.min(sharedDays * 0.05, 0.30);
/* Corruption bonus: +1% per 5 pts */
chance += Math.floor(prospect.corr / 5) * 0.01;
/* Penalties */
if (sv.factions.some(f => f.id !== factionId && f.members.includes(prospectId))) chance -= 0.10;
if (prospect.pairing === "low") chance -= 0.20;
return Math.max(0, Math.min(1, chance));
};
/* ── RESOLVE PARTY MINGLE ────────────────────────────────────────────────
Unchanged from original — handles faction party and clash events.
────────────────────────────────────────────────────────────────────── */
/* eventLabel — what to write in the infection register for anyone taken here.
Five very different events share this function (a faction party, the harem,
an activity, a lecture, a faction clash) and every one of them used to
record the same "At a gathering", which told the player nothing. Callers
that pass nothing still work; a faction party names itself below. */
/* `context` is "party" or "activity", forwarded to addSuspicion so the two
event-immunity upgrades can fire. Defaults to "party" because that is what
this resolver was written for; Activity and ClassLecture pass "activity"
so Crowd Cover covers them and Discreet Gatherings covers real parties,
and neither covers the other. */
window.resolvePartyMingle = function(input, locName, eventLabel, context) {
let sv = State.variables;
let results = [];
let targetList = [];
let ups = sv.upgrades || {};
let corrCapOf = function(ch) { return (typeof window.getCorrCap === "function") ? window.getCorrCap(ch) : 25; };
if (typeof input === "number" || typeof input === "string") {
let faction = sv.factions.find(f => f.id === input);
if (faction) {
targetList = faction.members;
/* FactionParty passes only the faction id — no location, no label
— so the register fell back to whatever room the girl happened
to be standing in. Name the party after the faction instead. */
if (!eventLabel) {
var _fn = window.factionDisplayName(faction);
/* Names are already possessive ("Marie's Friends"), so adding
another 's reads badly. An unknown faction yields "a group",
which needs no article in front of it. */
eventLabel = (_fn === "a group") ? "a group's party" : "the " + _fn + " party";
}
if (!locName) locName = faction.homeLocation || null;
}
} else if (Array.isArray(input)) {
targetList = input;
}
if (!targetList.length) return ["Event cancelled (no attendees)."];
let isAuthorityHere = window.isAuthorityPresent(locName || "Party");
/* Bred check — corruption 75 or more. Previously also required her to be
AT her cap, which made breeding impossible once the ceiling rose above
75 (Universal Threshold III, or any cap break). */
targetList.forEach(function(id) {
let c = sv[id];
if (c && c.corr >= 75 && !c.breed) {
c.breed = true;
let label = c.met ? `<b>${c.name}</b>` : `<b>someone</b>`;
results.push(`<span style="color:#ff5959">♥ ${label} was bred!</span>`);
}
});
/* Current infected count for hivemind cap check.
getHivemindLoad() is the single definition and excludes captives — this
used to count them, so a party could refuse to infect on a cap the rest
of the game did not agree you had reached. */
let infectedCount = window.getHivemindLoad();
let hivemindCap = sv.hivemindCap || 5;
let shuffled = [...targetList].sort(() => 0.5 - Math.random());
let actions = 0;
for (let i = 0; i < shuffled.length; i++) {
if (actions >= 2) break;
let c = sv[shuffled[i]];
if (!c) continue;
let label = c.met ? `<b>${c.name}</b>` : `<b>someone</b>`;
if (!c.infected) {
/* Must be met unless infectUnmet upgrade is owned */
if (!c.met && !ups.infectUnmet) continue;
/* AUTHORITY NEEDS THE UPGRADE HERE TOO.
InfectScene refuses an authority figure without infectAuthority,
but this resolver never checked -- so an activity, a lecture, a
party or a clash would take a police officer or a judge for free
and charge only the usual parasite. The gate belongs at every
door that infects, not just the deliberate one. */
if (c.trait === "authority" && !ups.infectAuthority) continue;
/* Hivemind cap check */
if (infectedCount >= hivemindCap) {
results.push(`<span style="color:#ff4444">🧠 Hivemind at capacity (${infectedCount}/${hivemindCap}) — cannot infect more.</span>`);
break;
}
if (sv.parasite >= 1) {
sv.parasite--;
window.recordInfection(c, "party", locName || c.location, eventLabel);
c.corr = Math.max(1, c.corr);
infectedCount++;
let gain = 5;
if (c.trait === "authority") gain = 20;
else if (c.trait === "flashpoint") gain = 12;
else if (c.trait === "influential") gain = 8;
if (isAuthorityHere) {
gain += 15;
let wLabel = c.met ? c.name : "someone";
results.push(`<span style="color:#ff4444">⚠ Authority witnessed you infect ${wLabel}!</span>`);
}
window.addSuspicion(gain, context || "party");
results.push(`You secretly infected ${label}.`);
actions++;
}
} else if (!c.breed) {
/* Corr tick respects cap */
if (c.corr < corrCapOf(c)) {
c.corr = Math.min(corrCapOf(c), c.corr + 5);
results.push(`You influenced ${label} (+5 corr).`);
actions++;
}
}
}
if (!actions && !results.length) results.push("You mingled, but found no opportunities.");
if (!State.temporary.dayLog) State.temporary.dayLog = [];
State.temporary.dayLog = results.concat(State.temporary.dayLog);
return results;
};
/* ── MASTER FACTION PROCESSOR ────────────────────────────────────────────
Called from processDayEnd. Runs all daily faction logic in correct order.
────────────────────────────────────────────────────────────────────── */
window.processFactions = function(log) {
let sv = State.variables;
if (!sv.factions) { sv.factions = []; return; }
if (!sv.territoryConflicts) sv.territoryConflicts = [];
/* Snapshot before anything moves, so reportFactionStatus can show deltas. */
sv._factionSnapshot = {};
sv.factions.forEach(function(f) {
sv._factionSnapshot[f.id] = {
corruption: f.corruption || 0,
stability: f.stability || 50,
stance: f.stance || "neutral"
};
});
/* ── PER-FACTION DAILY UPDATES ── */
sv.factions.forEach(function(faction) {
/* 1. Recalculate average corruption */
faction.corruption = faction.members.length > 0
? Math.floor(faction.members.reduce((s, id) => s + (sv[id] ? sv[id].corr : 0), 0) / faction.members.length)
: 0;
/* 2. Update location history + derive home location */
window.updateFactionLocationHistory(faction);
faction.homeLocation = window.deriveFactionHomeLocation(faction);
/* 3. Update stance */
window.updateFactionStance(faction);
/* 4. Stability tick (co-location deepening included here) */
window.tickFactionStability(faction);
/* 5. Player influence tick */
window.tickplayerInfluence(faction);
/* 6. Vector exchange (if receptive+) */
window.factionVectorExchange(faction, log);
/* 7. Weekly structural events (growth, expulsion, leader shift) */
window.checkFactionGrowth(faction, log);
window.checkFactionExpulsion(faction, log);
window.checkFactionLeaderShift(faction, log);
/* 8. Party check */
window.checkFactionParty(faction, log);
});
/* ── GLOBAL EVENTS (operate on faction list as a whole) ── */
/* 9. Rare events */
window.checkFactionDisband(log);
window.checkFactionMerge(log);
window.checkFactionSplit(log);
/* 10. Territory conflicts */
window.updateTerritoryConflicts(log);
/* 11. New formations */
window.checkFactionFormation(log);
/* 12. Process active directives (persistent effects, nest protection ticks) */
window.processDirectives(log);
window.proposeEnthralledAbductions(log);
window.checkFactionClashes(log);
/* 13. Nightly status line for every faction the player can see.
Structural events (joins, splits, parties) are rare by design, so on a
normal night the factions screen changed but the day log said nothing
at all. This guarantees at least one line per known faction, showing
what actually moved. */
window.reportFactionStatus(log);
/* Goal rolling used to happen here. It could not work: processFactions
runs at STEP 5 of processDayEnd, before the day is advanced at STEP 8,
so the five-day cooldown was always measured against yesterday and the
call returned early every night. It now happens at STEP 9b, after the
day advances and after completions have freed their slots. */
};
/* ── NIGHTLY FACTION STATUS ──────────────────────────────────────────────
Only things the player would want to act on.
This used to print a line for every faction every night, including the
two numbers that move on their own:
corr — the faction's AVERAGE member corruption, recalculated nightly
from the members themselves. It ticks up whenever any member
gains corruption, so "corr +2" was just restating a girl's own
progress in a less useful form, once per faction she is in.
stance — derived purely from how many members are infected or corrupted.
It cannot be influenced except by corrupting members, so a
stance change is a consequence of what you already did rather
than news.
Neither told the player anything they could act on, so both are gone.
What remains is what changes on its own or demands a decision: a faction
sliding toward collapse, and a directive running.
Structural events — recruitment, expulsion, leader shifts, merges, splits,
disbands, parties, clashes — were never handled here. They push their own
lines from their own functions and are unaffected.
────────────────────────────────────────────────────────────────────── */
/* Stability is only worth mentioning when it threatens something. These match
the gates the collapse and splinter events actually use. */
var FACTION_STAB_WARN = 30;
var FACTION_STAB_CRIT = 20;
window.reportFactionStatus = function(log) {
var sv = State.variables;
var snap = sv._factionSnapshot || {};
var lines = [];
(sv.factions || []).forEach(function(f) {
if (window.getFactionVisibility(f) === 0) return;
var was = snap[f.id];
var dStab = was ? (f.stability || 50) - was.stability : 0;
var stabNow = f.stability || 50;
var stabWas = was ? was.stability : stabNow;
var lowNow = stabNow <= FACTION_STAB_WARN;
var lowWas = stabWas <= FACTION_STAB_WARN;
var bits = [];
/* Stability, only while it threatens the faction or on the night it
crosses back over the line. */
if (lowNow || lowWas !== lowNow) {
var stabCol = stabNow <= FACTION_STAB_CRIT ? '#ff5555' : '#ffaa44';
if (!lowNow) {
bits.push('<span style="color:#44cc88">steady again (stability ' + stabNow + ')</span>');
} else {
bits.push('<span style="color:' + stabCol + '">' +
(stabNow <= FACTION_STAB_CRIT ? 'near collapse' : 'unstable') +
' \u2014 stability ' + stabNow +
(dStab !== 0 ? ' (' + (dStab > 0 ? '+' : '') + dStab + ')' : '') +
'</span>');
}
}
/* A directive you ordered is running, and it expires. */
if (f.directive && window.DIRECTIVE_DEFS[f.directive.id]) {
var dName = window.DIRECTIVE_DEFS[f.directive.id].name;
var dLeft = f.directive.daysLeft;
bits.push('\u26a1 ' + dName +
(dLeft ? ' (' + dLeft + 'd left)' : ' \u2014 resolves tonight'));
}
if (!bits.length) return;
lines.push('<span style="color:#7a7a8a;">\u25b8 <b>' +
window.factionDisplayNameCap(f) + '</b> \u2014 ' +
bits.join(' \u00b7 ') + '</span>');
});
if (!lines.length) return;
log.push('<span style="color:#555; font-size:0.9em;">\u2014 Factions \u2014</span>');
lines.forEach(function(l) { log.push(l); });
};
/* ── SYNC FACTION CONNECTIONS ────────────────────────────────────────────
Ensures every member of a faction has all other members in their
connections list. Safe to call repeatedly — never creates duplicates.
Called once per day and once at game start via StoryInit.
────────────────────────────────────────────────────────────────────── */
window.syncFactionConnections = function() {
var sv = State.variables;
(sv.factions || []).forEach(function(faction) {
var members = faction.members;
members.forEach(function(id) {
var c = sv[id];
if (!c) return;
if (!c.connections) c.connections = [];
members.forEach(function(otherId) {
if (otherId === id) return;
if (c.connections.indexOf(otherId) === -1) {
c.connections.push(otherId);
}
});
});
});
};/* =========================================================================
§ 9. FACTION SYSTEM — CAPTIVES, ABDUCTIONS & CLASHES
-------------------------------------------------------------------------
Part 2 of 4. Split out of the original JS-Factions, which had reached
2,000+ lines. Load order in StoryInit matters:
JS-Factions-Core -> JS-Factions-Events ->
JS-Factions-Clash -> JS-Factions-Directives
Each is eval'd separately, so nothing may rely on another file's
top-level const. Shared tuning values live on window.FACTION_CFG in
Core and are read from there everywhere else.
========================================================================= */
/* Aliases for the shared tuning values defined in JS-Factions-Core. */
var FACTION_STRUCTURAL_COOLDOWN = window.FACTION_CFG.STRUCTURAL_COOLDOWN;
var FACTION_RARE_COOLDOWN = window.FACTION_CFG.RARE_COOLDOWN;
var FACTION_PROTECTION_WINDOW = window.FACTION_CFG.PROTECTION_WINDOW;
var FACTION_PROTECTION_MIN = window.FACTION_CFG.PROTECTION_MIN;
var FACTION_HISTORY_DAYS = window.FACTION_CFG.HISTORY_DAYS;
var FACTION_HOME_MIN_VISITS = window.FACTION_CFG.HOME_MIN_VISITS;
var TERRITORY_MAX_PER_LOC = window.FACTION_CFG.TERRITORY_MAX;
var TERRITORY_CLASH_AFTER = window.FACTION_CFG.TERRITORY_CLASH;
window.proposeEnthralledAbductions = function(log) {
var sv = State.variables;
var ups = sv.upgrades || {};
if (!ups.factionAutoSpread) return;
var maxAgents = ups.factionAutoSpread2 ? 2 : 1;
sv.pendingAbductions = [];
/* Agents don't move every night. Without this a dominated faction proposes
an abduction every single morning and the +10 suspicion each stops being
a decision. T3 acts roughly every third night, T4 every other night. */
var actChance = ups.factionAutoSpread2 ? 0.50 : 0.30;
if (Math.random() >= actChance) return;
/* Eligible factions, strongest first so the best agents act */
var factions = (sv.factions || []).filter(function(f) {
return f.stance === "enthralled" || f.stance === "dominated";
});
if (!factions.length) return;
var claimed = {}; /* a girl can only be proposed once per night */
factions.forEach(function(faction) {
if (sv.pendingAbductions.length >= maxAgents) return;
/* Agents: infected members at corr 50+, not captive, somewhere */
var agents = faction.members.filter(function(id) {
var c = sv[id];
return c && c.infected && !c.arrested && !c.captive
&& c.corr >= 50 && c.location;
});
for (var i = 0; i < agents.length; i++) {
if (sv.pendingAbductions.length >= maxAgents) return;
var agent = sv[agents[i]];
/* Targets: co-located, outside the faction, not already taken */
var targets = sv.roster.filter(function(tid) {
var t = sv[tid];
if (!t || t.arrested || t.captive) return false;
if (t.location !== agent.location) return false;
if (faction.members.indexOf(tid) !== -1) return false;
if (claimed[tid]) return false;
if (!t.met) return false; /* strangers are never taken */
if (t.trait === "authority") return false; /* too risky */
if ((t.corr || 0) >= 50) return false; /* already far enough along */
if (!t.infected && !window.canInfect(t)) return false;
return true;
});
if (!targets.length) continue;
var targetId = targets[Math.floor(Math.random() * targets.length)];
claimed[targetId] = true;
sv.pendingAbductions.push({
agentId: agent.var,
targetId: targetId,
factionId: faction.id,
location: agent.location
});
}
});
if (sv.pendingAbductions.length > 0 && log) {
log.push('<span style="color:#ff8844;">🕷 <b>Enthralled Agents</b> — ' +
sv.pendingAbductions.length + ' abduction' +
(sv.pendingAbductions.length > 1 ? 's' : '') +
' proposed. Approve them in the morning.</span>');
}
};
/* Called from DayStart when the player approves one. */
window.acceptAbduction = function(index) {
var sv = State.variables;
var a = (sv.pendingAbductions || [])[index];
if (!a) return null;
var target = sv[a.targetId];
var agent = sv[a.agentId];
if (!target) return null;
if (!window.makeCaptive(a.targetId, 5)) return null;
window.addSuspicion(10);
if (!sv.pendingCaptiveIntro) sv.pendingCaptiveIntro = [];
sv.pendingCaptiveIntro.push(a.targetId);
return {
agent: agent ? agent.name : "An agent",
target: target.name,
location: a.location
};
};
/* ── DOMINATED FACTION CLASH ─────────────────────────────────────────────
A dominated faction crushes a non-dominated/non-enthralled faction.
Always wins. Captures members based on loser's stability as weight.
Dismantles loser and dominates their home location.
────────────────────────────────────────────────────────────────────── */
window.resolveDominatedClash = function(attacker, defender, log) {
var sv = State.variables;
/* Only girls the player has actually MET can be taken captive. A captive
gets a portrait, a morning scene and a name in the intro block — none of
which mean anything for a stranger, and makeCaptive's old
`met = true` shortcut skipped her real introduction entirely. */
var takeable = defender.members.filter(function(id) {
var c = sv[id];
return c && c.met && !c.arrested;
});
/* How many defenders become captives — stability as inverse weight */
/* High stability = fewer captives (they resist), low stability = more */
var stabilityFactor = 1 - ((defender.stability || 50) / 100);
var maxCaptives = takeable.length;
var captiveCount = maxCaptives === 0 ? 0 : Math.max(1,
Math.round(1 + (maxCaptives - 1) * stabilityFactor));
captiveCount = Math.min(captiveCount, maxCaptives);
var shuffled = takeable.slice().sort(function() { return Math.random() - 0.5; });
var captives = shuffled.slice(0, captiveCount);
var newCaptiveNames = [];
/* Snapshot the roster before makeCaptive starts pulling people out of it.
The display name has to be resolved here too — once the captives have
been removed the defender may have no known members left and would be
reported as "an unfamiliar group" even though you knew the girls who
were just dragged out of it. */
var defenderRoster = defender.members.slice();
var defenderLabel = window.factionDisplayName(defender);
captives.forEach(function(id) {
window.makeCaptive(id, 5);
var c = sv[id];
newCaptiveNames.push(c ? c.name : '???');
});
/* Survivors: some are absorbed into the winning faction, the rest scatter
and become unaffiliated. Previously every non-captive simply drifted
back into the general pool. */
var maxSize = (sv.settings && sv.settings.factionMaxSize) || 7;
var space = Math.max(0, maxSize - attacker.members.length);
var survivors = defenderRoster.filter(function(id) {
return captives.indexOf(id) === -1 && attacker.members.indexOf(id) === -1;
});
var absorbed = survivors.slice(0, Math.min(space, survivors.length));
absorbed.forEach(function(id) { attacker.members.push(id); });
if (absorbed.length) {
window.syncFactionConnections();
var aNames = absorbed.map(function(id) {
var c = sv[id];
return (c && c.met) ? c.name : "someone new";
});
log.push('<span style="color:#44cc88">' + aNames.join(', ') +
(absorbed.length === 1 ? ' was' : ' were') +
' absorbed into <b>' + window.factionDisplayName(attacker) + '</b>.</span>');
}
/* Dominate loser's home location */
var domLoc = defender.homeLocation;
if (domLoc && sv.goalBonuses && sv.goalBonuses.corruptedLocations) {
if (sv.goalBonuses.corruptedLocations.indexOf(domLoc) === -1) {
sv.goalBonuses.corruptedLocations.push(domLoc);
}
}
/* Dismantle defender */
sv.factions = sv.factions.filter(function(f) { return f.id !== defender.id; });
/* Boost attacker */
attacker.stability = Math.min(100, (attacker.stability || 50) + 15);
log.push(
'<span style="color:#ff4444">⚔ <b>' + window.factionDisplayNameCap(attacker) + '</b> crushed <b>' +
defenderLabel + '</b>.' +
(captiveCount > 0
? ' ' + captiveCount + ' captive' + (captiveCount > 1 ? 's' : '') + ' taken: ' + newCaptiveNames.join(', ') + '.'
: ' Nobody there was known to you — no captives taken.') +
'</span>'
);
if (domLoc) {
log.push('<span style="color:#bd59ff">☣ <b>' + domLoc + '</b> is now dominated.</span>');
}
/* Queue captive intro for DayStart */
if (!sv.pendingCaptiveIntro) sv.pendingCaptiveIntro = [];
captives.forEach(function(id) { sv.pendingCaptiveIntro.push(id); });
};
/* ── ENTHRALLED VS ENTHRALLED CLASH ─────────────────────────────────────
Two enthralled factions clash. No destruction unless player chooses.
Victor based on weighted score (corruption + stability + player influence).
Loser's uninfected members become captives.
Some loser members may join winner if there's space.
Player decides post-event whether to dismantle loser.
────────────────────────────────────────────────────────────────────── */
window.resolveEnthrallClash = function(f1, f2, log) {
var sv = State.variables;
var score = function(f) {
return (f.corruption || 0) * 0.5
+ (f.stability || 50) * 0.3
+ (f.playerInfluence || 0) * 0.2
+ (Math.random() * 15);
};
var s1 = score(f1);
var s2 = score(f2);
var winner = s1 >= s2 ? f1 : f2;
var loser = s1 >= s2 ? f2 : f1;
/* Loser's uninfected become captives — but only girls you have met. */
var captives = loser.members.filter(function(id) {
var c = sv[id];
return c && !c.infected && c.met && !c.arrested;
});
var loserRoster = loser.members.slice();
/* Resolve names before makeCaptive strips members out of the roster. */
var f1Label = window.factionDisplayNameCap(f1);
var f2Label = window.factionDisplayName(f2);
var winnerLabel = winner === f1 ? f1Label : f2Label;
var loserLabel = loser === f1 ? f1Label : f2Label;
captives.forEach(function(id) { window.makeCaptive(id, 5); });
/* Some loser members can join winner if space allows */
var space = Math.max(0, (sv.settings && sv.settings.factionMaxSize || 7) - winner.members.length);
var joinable = loserRoster.filter(function(id) {
return captives.indexOf(id) === -1 && winner.members.indexOf(id) === -1;
});
var joinCount = Math.min(space, Math.floor(Math.random() * (joinable.length + 1)));
var joiners = joinable.slice(0, joinCount);
joiners.forEach(function(id) {
winner.members.push(id);
window.syncFactionConnections();
});
winner.stability = Math.min(100, (winner.stability || 50) + 10);
loser.stability = Math.max(10, (loser.stability || 50) - 20);
/* This clash only fires when both share a home location — the loser is
driven off it and must find somewhere new. The winner keeps the turf. */
var contested = loser.homeLocation;
window.clearFactionHome(loser);
log.push(
'<span style="color:#ffcc00">⚡ <b>' + f1Label + '</b> and <b>' + f2Label +
'</b> clashed. <b>' + winnerLabel + '</b> prevailed.</span>'
);
if (contested) {
log.push('<span style="color:#ff8844">🏴 <b>' + loserLabel +
'</b> was driven out of <b>' + contested + '</b>.</span>');
}
if (captives.length > 0) {
var names = captives.map(function(id) {
var c = sv[id];
return (c && c.met) ? c.name : 'someone you have not met';
});
log.push('<span style="color:#ff8844">🔒 Captives: ' + names.join(', ') + '</span>');
}
if (joiners.length > 0) {
var jnames = joiners.map(function(id) {
var c = sv[id];
return (c && c.met) ? c.name : 'someone new';
});
log.push('<span style="color:#44cc88">' + jnames.join(', ') + ' joined <b>' + winnerLabel + '</b>.</span>');
}
/* Queue for DayStart player choice (dismantle loser or not) */
sv.pendingClash = {
type: "enthrall",
winnerId: winner.id,
loserId: loser.id,
captives: captives
};
if (captives.length > 0) {
if (!sv.pendingCaptiveIntro) sv.pendingCaptiveIntro = [];
captives.forEach(function(id) { sv.pendingCaptiveIntro.push(id); });
}
};
/* ── CHECK FOR CLASHES (called from processFactions) ── */
window.checkFactionClashes = function(log) {
var sv = State.variables;
if (!sv.factions) return;
/* ── PLAYER-ORDERED CLASHES (Start Clash directive) ──
Queued during the day, resolved here so they take a night and go
through the same win/lose logic as an organic clash. A dominated
attacker facing a weaker faction still crushes it; anything else is
contested and the attacker can lose. */
if (sv.orderedClashes && sv.orderedClashes.length) {
sv.orderedClashes.forEach(function(order) {
var atk = sv.factions.find(function(f) { return f.id === order.attackerId; });
var def = sv.factions.find(function(f) { return f.id === order.defenderId; });
if (!atk || !def) return; /* one of them died during the night */
var defStrong = def.stance === 'dominated' || def.stance === 'enthralled';
if (atk.stance === 'dominated' && !defStrong) {
window.resolveDominatedClash(atk, def, log);
} else {
window.resolveEnthrallClash(atk, def, log);
}
});
sv.orderedClashes = [];
}
var dominated = sv.factions.filter(function(f) { return f.stance === 'dominated'; });
var enthralled = sv.factions.filter(function(f) { return f.stance === 'enthralled'; });
var targets = sv.factions.filter(function(f) {
return f.stance !== 'dominated' && f.stance !== 'enthralled';
});
/* Dominated faction clashes: one per day, random target */
if (dominated.length > 0 && targets.length > 0 && Math.random() < 0.15) {
var attacker = dominated[Math.floor(Math.random() * dominated.length)];
var defender = targets[Math.floor(Math.random() * targets.length)];
window.resolveDominatedClash(attacker, defender, log);
}
/* Enthralled vs enthralled: only if 2+ enthralled and sharing a location */
if (enthralled.length >= 2 && Math.random() < 0.10) {
var f1 = enthralled[0];
var f2 = enthralled[1];
/* Only clash if they share a home location */
if (f1.homeLocation && f1.homeLocation === f2.homeLocation) {
window.resolveEnthrallClash(f1, f2, log);
}
}
};
/* ── REPLACE updateTerritoryConflicts ── */
/* =========================================================================
§ 9. FACTION SYSTEM — DIRECTIVES
-------------------------------------------------------------------------
Part 4 of 4. Split out of the original JS-Factions, which had reached
2,000+ lines. Load order in StoryInit matters:
JS-Factions-Core -> JS-Factions-Events ->
JS-Factions-Clash -> JS-Factions-Directives
Each is eval'd separately, so nothing may rely on another file's
top-level const. Shared tuning values live on window.FACTION_CFG in
Core and are read from there everywhere else.
========================================================================= */
window.DIRECTIVE_DEFS = {
/* ── TIER 1 ── stance: uneasy+ ── upgrade: factionDirectives1 ── */
"shadow": {
tier: 1,
stance: "uneasy",
type: "persistent",
duration: 3,
name: "Shadow",
desc: "All members roam to their anchor location for 3 days — makes them predictable and easy to find.",
apply: function(faction, log) {
/* Deliberately does nothing here. This used to write c.location
directly at DayEnd, which assignDailyLocations then overwrote at
DayStart a moment later — so the directive appeared to work and
changed nothing. Placement is now handled in
assignDailyLocations, which reads faction.directive.id. */
}
},
"coverStory": {
tier: 1,
stance: "uneasy",
type: "persistent",
duration: 3,
name: "Cover Story",
desc: "-5 suspicion per day while active.",
apply: function(faction, log) {
var sv = State.variables;
sv.suspicion = Math.max(0, (sv.suspicion || 0) - 5);
}
},
"markTerritory": {
tier: 1,
stance: "uneasy",
type: "instant",
name: "Mark Territory",
desc: "Nest detection chance halved at the faction's home location for 5 days.",
execute: function(faction, log) {
var sv = State.variables;
var loc = faction.homeLocation;
if (!loc) { log.push("No home location established."); return false; }
if (!sv.nestProtected) sv.nestProtected = {};
sv.nestProtected[loc] = (sv.nestProtected[loc] || 0) + 5;
log.push('<span style="color:#44cc88">🏴 <b>' + faction.name + '</b> marked <b>' + loc + '</b> — nest detection halved for 5 days.</span>');
return true;
}
},
"recruitment": {
tier: 1,
stance: "uneasy",
type: "instant",
name: "Recruitment",
desc: "The faction will attempt to recruit one unaffiliated girl tomorrow.",
execute: function(faction, log) {
var sv = State.variables;
var maxSize = sv.settings && sv.settings.factionMaxSize ? sv.settings.factionMaxSize : 7;
if (faction.members.length >= maxSize) {
log.push("Faction is already at maximum size.");
return false;
}
faction.pendingRecruitment = true;
log.push('<span style="color:#44aaff">★ <b>' + faction.name + '</b> will attempt to recruit tomorrow.</span>');
return true;
}
},
/* ── TIER 2 ── stance: receptive+ ── upgrade: factionDirectives2 ── */
"safeHouse": {
tier: 2,
stance: "receptive",
type: "persistent",
duration: 5,
name: "Safe House",
desc: "Nest at faction's home location cannot be detected or destroyed for 5 days.",
apply: function(faction, log) {
var sv = State.variables;
var loc = faction.homeLocation;
if (!loc) return;
if (!sv.nestProtected) sv.nestProtected = {};
sv.nestProtected[loc] = Math.max(sv.nestProtected[loc] || 0, 1);
}
},
"pressure": {
tier: 2,
stance: "receptive",
type: "persistent",
duration: 4,
name: "Pressure",
desc: "All infected faction members gain +3 corruption per day for 4 days.",
apply: function(faction, log) {
var sv = State.variables;
faction.members.forEach(function(id) {
var c = sv[id];
if (!c || !c.infected) return;
var cap = window.getCorrCap ? window.getCorrCap(c) : 25;
if (c.corr < cap) c.corr = Math.min(cap, c.corr + 3);
});
}
},
"forceParty": {
tier: 2,
stance: "receptive",
type: "instant",
name: "Force Party",
desc: "The faction throws a party tomorrow.",
execute: function(faction, log) {
/* BUGFIX: this used to push straight into sv.pendingParties without
setting sv.pendingPartiesDay, so TownHub's stale-invite sweep
deleted the party before the player could attend it. Flag the
faction instead and let checkFactionParty raise it tonight. */
faction.pendingParty = true;
log.push('<span style="color:#bd59ff">🎉 <b>' + faction.name + '</b> will throw a party tomorrow.</span>');
return true;
}
},
"expelMember": {
tier: 2,
stance: "receptive",
type: "instant",
name: "Expel Member",
desc: "Remove a specific member from the faction.",
/* targetId must be passed as extra arg */
execute: function(faction, log, targetId) {
var sv = State.variables;
if (!targetId || !faction.members.includes(targetId)) {
log.push("Target is not a member of this faction.");
return false;
}
faction.members = faction.members.filter(function(id) { return id !== targetId; });
window.syncFactionConnections();
var c = sv[targetId];
log.push('<span style="color:#ff8844">⬅ <b>' + (c ? c.name : targetId) + '</b> was expelled from <b>' + faction.name + '</b>.</span>');
return true;
}
},
/* ── TIER 3 ── stance: enthralled+ ── upgrade: factionDirectives3 ── */
"mergeFaction": {
tier: 3,
stance: "enthralled",
type: "instant",
name: "Merge Factions",
desc: "Merge this faction with another. Members and connections are combined.",
execute: function(faction, log, targetFactionId) {
var sv = State.variables;
var target = sv.factions.find(function(f) { return f.id === targetFactionId; });
if (!target) { log.push("Target faction not found."); return false; }
/* THE SIZE CAP APPLIES HERE TOO.
Recruitment refuses at maxSize, but this absorbed the whole
target with no check -- so merging two full factions produced
one of fourteen, past a limit every other join path respects
and past the number the player set in Settings.
Take as many as will fit, deepest hold first, so the merge
keeps the most useful members. The rest are left unaffiliated
rather than silently deleted. */
var maxSize = sv.settings && sv.settings.factionMaxSize ? sv.settings.factionMaxSize : 7;
var room = Math.max(0, maxSize - faction.members.length);
var joining = target.members
.filter(function(id) { return !faction.members.includes(id); })
.sort(function(a, b) { return (sv[b] ? sv[b].corr : 0) - (sv[a] ? sv[a].corr : 0); });
joining.slice(0, room).forEach(function(id) { faction.members.push(id); });
var leftOut = joining.length - Math.min(room, joining.length);
if (leftOut > 0) {
log.push('<span style="color:#888">' + leftOut +
' had nowhere to go and drifted off.</span>');
}
sv.factions = sv.factions.filter(function(f) { return f.id !== targetFactionId; });
window.syncFactionConnections();
faction.stability = Math.max(30, (faction.stability || 50) - 10);
log.push('<span style="color:#44cc88">🤝 <b>' + faction.name + '</b> merged with <b>' + target.name + '</b>.</span>');
return true;
}
},
"splitFaction": {
tier: 3,
stance: "enthralled",
type: "instant",
name: "Split Faction",
desc: "Split half the faction members into a new faction.",
execute: function(faction, log) {
var sv = State.variables;
if (faction.members.length < 4) {
log.push("Faction is too small to split (need 4+ members).");
return false;
}
var half = Math.floor(faction.members.length / 2);
var shuffled = faction.members.slice().sort(function() { return Math.random() - 0.5; });
var newMembers = shuffled.slice(0, half);
faction.members = shuffled.slice(half);
var newLeader = newMembers[0];
var newFaction = {
id: window.allocFactionId(),
leader: newLeader,
members: newMembers,
name: (sv[newLeader] ? sv[newLeader].name : "New") + "'s Group",
corruption: 0,
stability: 40,
formed: sv.day,
lastStructuralChange: sv.day,
lastEvent: 0,
homeLocation: faction.homeLocation,
locationHistory: [],
stance: "neutral",
rivalOf: [],
playerInfluence: 0,
directive: null
};
sv.factions.push(newFaction);
window.syncFactionConnections();
log.push('<span style="color:#88aaff">✂ <b>' + faction.name + '</b> split. New faction: <b>' + newFaction.name + '</b>.</span>');
return true;
}
},
"betrayal": {
tier: 3,
stance: "enthralled",
type: "instant",
name: "Betrayal",
desc: "The faction turns on one of its own. She is seized and held captive for 5 days, and the faction loses cohesion for it. A pair will not survive it.",
/* targetId must be passed as extra arg */
execute: function(faction, log, targetId) {
var sv = State.variables;
if (!targetId || faction.members.indexOf(targetId) === -1) {
log.push("Target is not a member of this faction.");
return false;
}
if (targetId === faction.leader) {
log.push("They will not turn on their own leader.");
return false;
}
var c = sv[targetId];
if (!c) { log.push("Target not found."); return false; }
if (c.captive) { log.push("She is already held."); return false; }
if (c.arrested) { log.push("She is detained."); return false; }
if (!c.met) { log.push("You have not met her."); return false; }
/* makeCaptive strips her from the faction, so read the name first.
A two-girl faction is left with one member and checkFactionDisband
dissolves it the same night, with its own log line. That is the
correct outcome — one of them betrayed the other and there is no
group left. Nothing here needs to prevent it. */
var name = c.name;
if (!window.makeCaptive(targetId, 5)) {
log.push("She could not be taken.");
return false;
}
faction.stability = Math.max(0, (faction.stability || 50) - 25);
faction.lastStructuralChange = sv.day;
window.addSuspicion(10);
log.push('<span style="color:#ff4444">🗡 <b>' + faction.name +
'</b> turned on <b>' + name +
'</b>. She is held captive for 5 days. Stability −25 · +10 suspicion.</span>');
return true;
}
},
"infiltrate": {
tier: 3,
stance: "enthralled",
type: "instant",
name: "Infiltrate",
desc: "Send one of this faction's own members, at corr 50+, to take over another faction. She leaves this faction and becomes the target's leader.",
execute: function(faction, log, agentId, targetFactionId) {
var sv = State.variables;
var target = sv.factions.find(function(f) { return f.id === targetFactionId; });
if (!target) { log.push("Target faction not found."); return false; }
if (target.id === faction.id) { log.push("A faction cannot infiltrate itself."); return false; }
var agent = sv[agentId];
if (!agent) { log.push("Agent not found."); return false; }
/* The agent must be a MEMBER of the faction giving the order. The
old rule was the exact opposite — it demanded she be in no
faction at all — which made the directive nonsensical (you were
asking a dominated faction to send someone who wasn't in it) and,
in practice, only captives and stragglers ever qualified. */
if (faction.members.indexOf(agentId) === -1) {
log.push("She is not a member of this faction.");
return false;
}
if (agent.corr < 50) { log.push("Agent must have corr 50+."); return false; }
if (agent.captive) { log.push("She is being held captive."); return false; }
if (agent.arrested) { log.push("She is detained."); return false; }
if (target.members.indexOf(agentId) !== -1) {
log.push("She is already in that faction.");
return false;
}
if (faction.members.length <= 1) {
log.push("Sending her would leave the faction empty.");
return false;
}
/* She leaves the sending faction... */
faction.members = faction.members.filter(function(id) { return id !== agentId; });
if (faction.leader === agentId) {
/* Promote the next highest-corruption member rather than
leaving a dangling leader id. */
var succ = null, best = -1;
faction.members.forEach(function(id) {
var c = sv[id];
if (c && c.corr > best) { best = c.corr; succ = id; }
});
faction.leader = succ;
if (succ && sv[succ]) faction.name = sv[succ].name + "'s Friends";
}
/* ...and takes over the target. */
target.members.unshift(agentId);
target.leader = agentId;
target.stability = Math.max(20, (target.stability || 50) - 20);
faction.lastStructuralChange = sv.day;
target.lastStructuralChange = sv.day;
window.syncFactionConnections();
log.push('<span style="color:#ff88cc">🕵 <b>' + agent.name + '</b> left <b>' + faction.name +
'</b> and took control of <b>' + target.name + '</b>.</span>');
return true;
}
},
"concentrate": {
tier: 3,
stance: "enthralled",
type: "instant",
name: "Concentrate",
desc: "Force all faction members to move to the faction's home location tomorrow.",
execute: function(faction, log) {
var sv = State.variables;
var loc = faction.homeLocation;
if (!loc) { log.push("No home location established."); return false; }
/* Was { id: "shadow" } — which sent everyone to their own anchors
instead of to the faction's home, i.e. it silently performed the
OTHER directive. assignDailyLocations now reads this id. */
faction.directive = { id: "concentrate", daysLeft: 1 };
log.push('<span style="color:#88aaff">📍 <b>' + faction.name + '</b> will concentrate at <b>' + loc + '</b> tomorrow.</span>');
return true;
}
},
/* ── TIER 4 ── stance: dominated ── upgrade: factionDirectives4 ── */
"dismantle": {
tier: 4,
stance: "dominated",
type: "instant",
name: "Dismantle",
desc: "Dissolve the faction entirely. All members become unaffiliated.",
execute: function(faction, log) {
var sv = State.variables;
sv.factions = sv.factions.filter(function(f) { return f.id !== faction.id; });
log.push('<span style="color:#ff4444">💀 <b>' + window.factionDisplayNameCap(faction) + '</b> has been dismantled.</span>');
return true;
}
},
"startClash": {
tier: 4,
stance: "dominated",
type: "instant",
name: "Start Clash",
desc: "Order this faction to move against a target. The clash resolves tonight — a dominated faction crushes a weaker rival, but an equal fights back.",
execute: function(faction, log, targetFactionId) {
var sv = State.variables;
var target = sv.factions.find(function(f) { return f.id === targetFactionId; });
if (!target) { log.push("Target faction not found."); return false; }
if (target.id === faction.id) { log.push("A faction cannot clash with itself."); return false; }
/* This used to call resolveDominatedClash() the instant the button
was pressed — an immediate, guaranteed, free victory that
dismantled the target and took captives with no roll and no
night in between. The directive now QUEUES the clash; it is
resolved tonight by checkFactionClashes, through the same two
paths an organic clash uses:
dominated vs weaker -> resolveDominatedClash (crushing)
anything else -> resolveEnthrallClash (contested)
So ordering a clash against a real rival is a gamble, and your
own faction can come off worse. */
if (!sv.orderedClashes) sv.orderedClashes = [];
sv.orderedClashes.push({ attackerId: faction.id, defenderId: target.id });
log.push('<span style="color:#ffcc00">⚔ <b>' + window.factionDisplayNameCap(faction) + '</b> will move against <b>' +
window.factionDisplayName(target) + '</b> tonight.</span>');
return true;
}
}
};
/* ── STANCE ORDER for comparison ── */
window.STANCE_ORDER = ["neutral", "uneasy", "receptive", "enthralled", "dominated"];
window.stanceAtLeast = function(stance, required) {
return window.STANCE_ORDER.indexOf(stance) >= window.STANCE_ORDER.indexOf(required);
};
/* =========================================================================
ISSUE DIRECTIVE
========================================================================= */
window.issueDirective = function(factionId, directiveId, extraArg, extraArg2) {
var sv = State.variables;
var faction = sv.factions.find(function(f) { return f.id === factionId; });
if (!faction) return { ok: false, msg: "Faction not found." };
var def = window.DIRECTIVE_DEFS[directiveId];
if (!def) return { ok: false, msg: "Unknown directive." };
/* ── Upgrade check ── */
var upgradeMap = { 1: "factionDirectives1", 2: "factionDirectives2", 3: "factionDirectives3", 4: "factionDirectives4" };
var requiredUpgrade = upgradeMap[def.tier];
if (requiredUpgrade && !window.hasUpgrade(requiredUpgrade)) {
return { ok: false, msg: "Requires upgrade: " + requiredUpgrade + "." };
}
/* ── Stance check ── */
if (!window.stanceAtLeast(faction.stance, def.stance)) {
return { ok: false, msg: "Faction stance too low. Need: " + def.stance + ", current: " + faction.stance + "." };
}
/* ── Persistent: replace existing directive ── */
if (def.type === "persistent") {
faction.directive = { id: directiveId, daysLeft: def.duration };
var log = [];
def.apply(faction, log); /* apply immediately on day of issue */
return { ok: true, msg: "Directive issued: " + def.name + " (" + def.duration + " days).", log: log };
}
/* ── Instant: execute immediately ── */
if (def.type === "instant") {
var log = [];
var result = def.execute(faction, log, extraArg, extraArg2);
faction.directive = null; /* clear any persistent */
return { ok: result, msg: log.join(" "), log: log };
}
return { ok: false, msg: "Unknown directive type." };
};
/* =========================================================================
PROCESS ACTIVE DIRECTIVES (called nightly from processFactions)
========================================================================= */
window.processDirectives = function(log) {
var sv = State.variables;
(sv.factions || []).forEach(function(faction) {
if (!faction.directive) return;
var d = faction.directive;
var def = window.DIRECTIVE_DEFS[d.id];
/* "concentrate" is an instant directive that parks a one-day movement
order on the faction. It must survive until assignDailyLocations has
read it at the next DayStart, so tick it like a persistent one
rather than clearing it on sight. */
if (d.id === "concentrate") {
d.daysLeft--;
if (d.daysLeft <= 0) faction.directive = null;
return;
}
if (!def || def.type !== "persistent") { faction.directive = null; return; }
/* Apply nightly effect */
def.apply(faction, log);
/* Special: safeHouse — mark nest protection as active */
if (d.id === "safeHouse" && faction.homeLocation) {
if (!sv.nestProtected) sv.nestProtected = {};
sv.nestProtected[faction.homeLocation] = Math.max(
sv.nestProtected[faction.homeLocation] || 0, 1
);
}
d.daysLeft--;
if (d.daysLeft <= 0) {
log.push('<span style="color:#666">📋 <b>' + window.factionDisplayNameCap(faction) + '</b>\'s directive <em>' + def.name + '</em> has expired.</span>');
faction.directive = null;
}
});
/* Tick nestProtected days down */
if (sv.nestProtected) {
Object.keys(sv.nestProtected).forEach(function(loc) {
sv.nestProtected[loc]--;
if (sv.nestProtected[loc] <= 0) delete sv.nestProtected[loc];
});
}
};
/* =========================================================================
AVAILABLE DIRECTIVES (UI helper)
Returns the directive defs a faction can currently be issued, filtered by
owned upgrade tier and current stance. Used by the Factions passage.
========================================================================= */
window.DIRECTIVE_TARGETED = ["expelMember", "betrayal", "mergeFaction", "startClash", "infiltrate"];
window.getAvailableDirectives = function(factionId) {
var sv = State.variables;
var faction = (sv.factions || []).find(function(f) { return f.id === factionId; });
if (!faction) return [];
var upgradeMap = { 1: "factionDirectives1", 2: "factionDirectives2",
3: "factionDirectives3", 4: "factionDirectives4" };
var out = [];
Object.keys(window.DIRECTIVE_DEFS).forEach(function(id) {
var def = window.DIRECTIVE_DEFS[id];
if (!def) return;
var req = upgradeMap[def.tier];
if (req && !(typeof window.hasUpgrade === "function" && window.hasUpgrade(req))) return;
if (!window.stanceAtLeast(faction.stance, def.stance)) return;
out.push({
id: id,
name: def.name,
desc: def.desc,
tier: def.tier,
type: def.type,
needsTarget: window.DIRECTIVE_TARGETED.indexOf(id) !== -1
});
});
out.sort(function(a, b) { return a.tier - b.tier; });
return out;
};<div class="narrative-box">
$name lets himself in a little after eight.
His own key, his own door, the hall light already on because it is always already on. There is a bag of washing over his shoulder and a mug of his still in the sink from Friday, and nothing about him coming through this door on a Tuesday evening is worth anybody's attention.
He has spent the walk deciding how to be, and by the time he is inside he has it.
The trick — he worked it out somewhere around the corner shop — is that none of this shows. Not one second of the last four days has been visible from the outside. Vanna thought he'd gone a funny colour. Marie thought he looked rough. Nobody has looked at him and seen anything except a tired student, because there is nothing to see: it is all interior, all of it, every last inch.
So he can carry it. He is fairly sure he can carry it indefinitely.
That thought ought to be a comfort and it is not one, and he does not examine why.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Scarlet')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Scarlet</div></div>
<<speech "Scarlet">>"He returns! Where were you last night?"<</speech>>
<<charLink "scarlet" "Scarlet">> is upside down over the arm of the couch under a fuzzy blanket with a snack bag balanced on her stomach, and she rights herself with enormous effort in order to point at him properly.
<<speech "$name">>"Home. Jewelz picked up shifts, so I stayed on."<</speech>>
<<speech "Scarlet">>"You said Monday."<</speech>>
<<speech "$name">>"I know. There was nobody in the house."<</speech>>
<<speech "Scarlet">>"Fine. Excused."<</speech>>
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Claire')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Claire</div></div>
<<speech "Claire">>"He's not excused. Your mug's been in that sink since Friday and Karlee's been leaving it there on purpose."<</speech>>
<<charLink "claire" "Claire">> is cross-legged on the floor in front of the low coffee table, painting one thumbnail with the concentration of a surgeon.
<<speech "$name">>"On purpose?"<</speech>>
<<speech "Claire">>"As a statement. She's said nothing about it for four days and it's been the loudest thing in this flat."<</speech>>
<<speech "$name">>"I'll wash it up."<</speech>>
<<speech "Claire">>"Too late. It's art now."<</speech>>
He drops the washing by the door and toes his shoes off and goes through to the kitchenette to get a glass of water, and while he is filling it Claire says something to Scarlet about a seminar and Scarlet answers with her mouth full, and it is a completely ordinary Tuesday evening in the flat where he lives.
And underneath it, unbroken since he opened his eyes this morning, is the wanting.
It has not eased once. It did not ease on the walk. It has been sitting in him all day at a pitch he did not know a body could hold — a heavy, low, constant ache, the kind that makes his hands unsteady if he thinks about it, and he has stopped being able not to think about it. He is aware of the weight of his own clothes. He is aware of the temperature of the room. He drank two glasses of water at the tap and neither of them touched anything.
He puts the glass down and rests both palms flat on the counter and breathes out slowly.
Nobody notices. That is the thing. He is standing four feet from two women he lives with, so wound up he can hear his own pulse, and Claire is arguing about a seminar and Scarlet is eating crisps and neither of them has the faintest idea.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Karlee')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Karlee</div></div>
<<charLink "karlee" "Karlee">> comes out of her room with a laundry basket on her hip.
<<speech "Karlee">>"You were supposed to be back yesterday."<</speech>>
<<speech "$name">>"I know."<</speech>>
<<speech "Karlee">>"You had the shopping list."<</speech>>
<<speech "$name">>"I've still got the shopping list."<</speech>>
<<speech "Karlee">>"Then you can do it tomorrow, and you can do the bins, because Claire has decided the bins are a group responsibility that nobody is individually accountable for."<</speech>>
<<speech "Claire">>"That's a direct quote and I stand by it."<</speech>>
<<speech "$name">>"I'll do the bins."<</speech>>
<<speech "Karlee">>"Good. That's all I wanted."<</speech>>
She goes past him to the machine, close enough that her shoulder passes a few inches from his chest.
<video src="img/Characters/Karlee/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
It takes him standing at the counter with a glass of water in his hand.
There is no warning any more and no gap between one state and the other, and what arrives is not something he watches — it is something he is inside, sudden and hot and total, and his whole body responds to it as though it were happening. Every part of him that had been aching all day gets an answer at once, and the answer is enormous, and it lasts four seconds.
Then the kitchenette, and the tap dripping, and Karlee crouched at the machine with her back to him, sorting a dark load out of a light one.
She has not looked up. She did not see anything. There was nothing to see.
$name drinks the water. His hand is not quite steady on the glass and he puts it down before that becomes visible, and finds that his voice comes out perfectly level.
<<speech "$name">>"Do you want the dark stuff in with that?"<</speech>>
<<speech "Karlee">>"If it's not wet, yes."<</speech>>
<<speech "$name">>"It's not wet."<</speech>>
He hands her the bag from the door and she takes it without looking round.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
It happens twice more before nine.
Scarlet gets up to reach a bowl down from the high shelf and her top rides up an inch.
<video src="img/Characters/Scarlet/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Claire leans across him to get the remote off the arm of the couch.
<video src="img/Characters/Claire/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Both of them take him completely, and both are heavier and longer than anything on Monday, and afterwards there is no relief in the room whatsoever — the pull comes back at full strength within seconds, worse for having been fed, the way one drink is worse than none.
And through both of them he keeps talking.
That is the discovery of the evening and he cannot get past it. He answers Scarlet about the bowl. He tells Claire the remote was under the cushion. His voice does what it always does. Somewhere in the middle of the second one he hears himself finish a sentence he was not present for, correctly, in the right tone, and Claire laughs at it.
He is sitting in his own front room with two of his housemates, four feet away from both, so far past the edge of himself that he can barely see the edge — and from the outside he is a tired student on a Tuesday.
//Closer.//
If it is a word at all. It is barely that: a pressure with a direction, the same shapeless pull as the stairs and the doorway and the hall at home, and it does not care that Claire is mid-anecdote or that Scarlet has crisps or that he lives here. It wants the distance gone. It has wanted that and nothing else since Saturday.
$name stays exactly where he is.
Not out of strength. He is not sure there is any strength involved. He stays because his hands are locked together between his knees and because the whole of his attention is going into keeping his face doing what a face does, and there is nothing left over to move with.
<<speech "Claire">>"You're quiet."<</speech>>
<<speech "$name">>"Long day. I walked back from the other side of town and I've done nothing but stand up since eight this morning."<</speech>>
<<speech "Claire">>"You could've got the bus like a normal person."<</speech>>
They go on. $name laughs in the right places. At half nine he says he's going to turn in early because he's been sleeping badly, and Scarlet says something about how he's been saying that for a week, and nobody looks at him twice.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
His room is exactly as he left it on Friday, down to the ring on the desk where the mug was.
He lies on the bed with the light off and his clothes on and lets go of the performance, and what is underneath it is very bad.
There is no version of lying still that works. He is hard and he has been hard, on and off, since the kitchen, and the ache has stopped being localised — it is in his stomach and his chest and the backs of his hands. He deals with it, once, viciously, and it changes nothing at all, and afterwards he lies in the dark with his heart going and the want sitting there completely undiminished, exactly as it did on Saturday night.
Through the wall he can hear the three of them in the front room. Claire's laugh. The tap. A cupboard door.
He is aware of every one of them through nine inches of plasterboard, and there is a part of him now that regards nine inches of plasterboard as an obstacle rather than a wall.
He puts his hand flat over the mark on his side.
It is warm. It has been warm since Saturday. Under his palm, very faintly, something moves — and this time it does not stop when he notices. It carries on doing whatever it is doing, unhurried, entirely unbothered by being felt.
He tries to be frightened and mostly isn't, and understands that the not-being-frightened is the worst symptom of the four days.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
At some point after two he stops being able to tell whether he is asleep.
There is no dream. There is no vision. There is only, gradually, the sense of a great deal of noise stopping — noise he had not known was noise until it went — and something moving into the space it leaves behind.
It is not born the way a person is born. There is no first breath and no cry. There is a long slow settling, like a house going quiet after everybody has gone to bed, and then simply the fact of it: something that was dying in a clearing on Saturday, that has spent four days building itself out of him, finished.
And it does not stay where it was.
He has spent four days locating it — the mark on his side, the warmth, the thing under his palm. That is not where it is now. What is behind his eyes at three in the morning is not a passenger and is not below him and is not something he could put a hand over.
The last thing he feels before morning is not a word.
It is attention. Something turning to look at him, from inside his own head, for the first time.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
He wakes before the alarm.
No headache. No thirst. The taste of copper is gone out of his mouth and he feels — extraordinary is the only honest word. Rested to the bone. Clear-headed. Better than he has felt in months.
And he knows where they are.
Not by hearing them; the flat is silent. He simply knows, the way he knows where his own hands are without looking, that Karlee is awake and in the kitchen, that Claire is in the shower, that Scarlet has not got up yet.
$name sits on the edge of the bed in the grey light and turns that over, and notices that he is calm about it. He has been calm about very little since Saturday. He is entirely calm about this.
The wanting has not gone anywhere. It is going to be there when he opens the door and it is going to be there all day, and he understands now — with a clarity four days have earned him — that it is simply how he lives.
But it is not clawing at him this morning. It has stopped straining at the end of its rope and lain down: near him, warm, patient, and wide awake.
He gets up, and puts a shirt on, and goes to put the kettle on for Karlee.
<div style="text-align:center; margin-top:36px;">[[A new life (1)|DayStart]]</div>
</div>
<div class="narrative-box">
/* THE INTRO PROSE. Split out of `Start` so that $name is already set before
a single line of it renders -- see the note in `Start`. The text is
unchanged; only its home is new. */
The town is small enough that you can walk out of it in forty minutes, and it has absolutely everything. A hospital that people from three counties drive to. A courthouse. A police station with more officers than the crime rate justifies. A mall on the north side, a cinema, a spa, a hotel that hosts weddings for people who don't live here.
The reason for all of it sits up on the hill in a ring of houses with gates on them. Money came here at some point and never left — old money, new money, people who made it somewhere else and retired to somewhere quiet. They pay for the hospital wing and the theatre and the sports facilities, and in return the town does not ask them very much.
And they came for the schools. That is what the town is genuinely known for, if it's known for anything: the schools here are excellent, absurdly so for a place this size, and families move in on the strength of a prospectus. Which means the classrooms are full of the daughters of people with money, and also full of everyone else, and the two have been going to school together for long enough that nobody thinks about it much.
$name's family lives on the other side of that hill, on the outskirts, in a house with four people in it and one bathroom.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
Their parents died when $name was nine.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Jewelz')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Jewelz</div></div>
<<charLink "jewelz" "Jewelz">> was sixteen. There was an aunt two hundred miles away who offered, and there was a social worker who came round twice, and there was <<charLink "melissa" "Melissa">> — their godmother, who lives fifteen minutes away and who arrived on the second day with three days of food in the back of her car and did not go home for a fortnight. Between the two of them the answer worked out to: the children stay in the house.
Jewelz was sixteen and she took it the way you take a shift nobody else will cover. She left school. She worked at the restaurant and then at the restaurant and the shop, and then for two years at the restaurant and the shop and a cleaning job that started at five in the morning, and she has never once, in nine years, said a word about it in front of them. What she did instead was arrange things so that nothing looked like it was missing. There were birthdays. There were school trips paid for in instalments. There was a Christmas she is still paying off, quietly, on a card she doesn't think anybody knows about.
$name did what a nine-year-old and then a twelve-year-old and then a sixteen-year-old could do. Chores first, then the neighbours' gutters and fences and flat-pack furniture for whatever they'd pay, then anything with a screwdriver in it. It is not a talent. It is just the thing he found he could contribute, and he has been contributing it ever since.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Elsa')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Elsa</div></div>
<<charLink "elsa" "Elsa">> is the middle one. She could not be less like him — loud, quick, in the middle of a group wherever she goes, forever making plans she forgets by Thursday. What people miss about Elsa is that she is the one who learned to cook properly at thirteen, and the one who kept the household budget in a notebook for four years because Jewelz was too tired at the end of a shift to do sums. She is unreliable about everything except the things that matter, and she is fiercely, unreasonably loyal.
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Emily')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Emily</div></div>
<<charLink "emily" "Emily">> is the newest, and the reason she is here is $name.
She was sitting alone at lunch. Not once — every day, three weeks running, at the end of a table with her bag on the seat beside her so it would look like somebody was coming back. $name noticed in the first week and did nothing about it for two more, because he is not the kind of person who walks up to people, and then one day he sat down opposite her and said something so unremarkable that neither of them can remember what it was.
It took two months to get the story out of her, in pieces, mostly sideways. Her parents were not people who should have had a child. What had been done to her in that house was not a single event you could point at and report; it was the weather, every day, for years.
$name told Jewelz. Jewelz asked exactly two questions, then made up the spare room, and then went and had a conversation with somebody official that $name was not present for and has never asked about.
That was a year and four months ago. She still runs the shower quietly so as not to use too much hot water, and still apologises when she takes the last of the milk, and still puts her bag on the seat beside her out of habit. But she reads now, in the front room, with her feet up. She laughs at Elsa. She has started leaving things out — a mug, a hairbrush, a book face-down on the arm of the chair — which Jewelz says is the best sign there is.
$name spent a great many hours that first month sitting up with her when she couldn't sleep, mostly not talking. He has never mentioned that to anyone either. He is aware, in a way he doesn't examine, that he is more protective of Emily than he has any right to be.
Four people, one bathroom, and a hot water tank with opinions.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
Saturday morning. $name is in the hall with a screwdriver and the door of the airing cupboard, which has been catching on its frame for the better part of a year.
<<speech "Jewelz">>(from the kitchen, not looking up) "If you strip that screw I'm not buying a new one."<</speech>>
<<speech "$name">>"I'm not going to strip it."<</speech>>
<<speech "Jewelz">>"You stripped the one on the gate."<</speech>>
<<speech "$name">>"The gate was already broken when I got to it. That screw had been painted over twice."<</speech>>
<<speech "Jewelz">>"Mm."<</speech>>
Elsa comes down the stairs two at a time with her phone against her ear and a hairbrush in the other hand, tells whoever is on the phone that she'll be outside in five minutes, and steps over the toolbox without breaking stride.
<<speech "Elsa">>"Is that the cupboard? That's been like that for months."<</speech>>
<<speech "$name">>"I know. I'm doing it now."<</speech>>
<<speech "Elsa">>"I'm just saying. Months."<</speech>>
She is gone before he can answer. The front door bangs. Somewhere above, the shower starts, which means the kitchen tap is about to run cold.
<<speech "Jewelz">>"Emily. Emily, love, give it a minute — I've got the pan on."<</speech>>
The shower stops. Then, after a moment, starts again, quieter, as though the person running it is trying to use less water out of politeness.
$name gets the door off its hinges, shaves two millimetres off the bottom edge with a plane that belonged to a man he can only really remember the hands of, and puts it back. It swings. It shuts. It is the most satisfying thing he will do all week.
<<speech "Jewelz">>(appearing in the doorway, drying her hands) "It shuts."<</speech>>
<<speech "$name">>"It shuts."<</speech>>
<<speech "Jewelz">>"Don't get smug. The bathroom window's next, and that one's swollen."<</speech>>
Emily comes down with her hair wet, sees $name opening and shutting the cupboard door to demonstrate, and gives him the small quick smile she gives when she wants to say something and can't find the front of it.
<<speech "Emily">>"You fixed it."<</speech>>
<<speech "$name">>"Don't tell Elsa. She'll want the wardrobe doing."<</speech>>
<<speech "Emily">>"She already asked me to ask you."<</speech>>
<<speech "$name">>"Of course she did. Tell her the hinge is bent and I need a part."<</speech>>
<<speech "Emily">>"Is it bent?"<</speech>>
<<speech "$name">>"It will be by the time she checks."<</speech>>
That gets a real laugh out of her, brief and surprised, and she goes to put the kettle on.
$name puts the tools away. The house settles into its afternoon: Jewelz on the phone to someone about a shift, Emily on the sofa with a book she has been reading for a fortnight, the radiator ticking. He puts his boots on.
<<speech "Jewelz">>(hand over the phone) "Where are you going?"<</speech>>
<<speech "$name">>"Out. Walk."<</speech>>
<<speech "Jewelz">>"Back for six. It's your turn to cook and I'm not doing it for you."<</speech>>
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
He does this most weekends.
Out past the last row of houses, along the verge where the pavement gives up. Past the turning for the industrial park. Past the long grey fence of the research site — half a mile of it, no signage worth reading, a gatehouse and a car park you can see a corner of. Somebody's uncle works there. Somebody's cousin got a job in the canteen. Ask anyone in town what actually happens inside and you will get a shrug and a theory.
Then the fence ends and the trees start.
$name walks because the house has four people in it and one bathroom, and because being the one who fixes things is easier when nobody is watching you do it.
The path he usually takes bends east along the ridge. Today he goes down instead, into the older part of the wood where the trees stand closer and the light comes through green and thin, and the ground is soft with a hundred years of leaf fall.
He is not thinking about anything in particular. That is the point of it.
The clearing is not on the path. He finds it because the ground drops away and he goes down to look, and then he is standing in a gap in the canopy about the size of the front room at home, with the light coming straight down into it.
There is a ring of mushrooms in the middle of the grass.
They are pale, almost white, and they are arranged in a circle that is too round. $name has seen fairy rings before — everyone who walks in woods has seen fairy rings. They are ragged. They spread the way a stain spreads. This one has an edge to it, a deliberateness, like something drawn with a compass and a steady hand.
Most of them are dead.
That is what he notices when he crouches down. The ring is collapsing. The caps have gone soft and grey and are folding in on themselves, and the grass beneath them is yellow and wet with whatever comes out of a mushroom when it fails. Whatever this was, it happened days ago, and it did not work.
One is still standing. Right at the centre, small, no taller than his thumb, its cap still pale and still whole. And while he is looking at it, it moves.
Not in the wind. There is no wind down here. It contracts, once, the way a throat does.
$name should stand up and walk back to the path. He knows the shape of that thought clearly, the way you know not to put your hand on a hot pan.
But he has spent a year and four months learning what it looks like when something is failing quietly in a place where nobody goes, and he cannot leave it alone. That is not curiosity. He wishes it were curiosity. It would be simpler.
He reaches out and touches it.
The pain is instant and specific, low on his left side, under the ribs — not a sting or a scratch but a puncture, deep and hot, as though something has gone into him with intent. He is on his back before he understands he has fallen. His hand comes away from his side wet.
The canopy turns above him. The light coming down through it goes narrow, then narrower, then closes.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
When he comes round the light has moved. It is coming in low and orange from the west, which means an hour, maybe more.
He sits up slowly, waiting for it to hurt.
It doesn't.
He gets his shirt up. There is blood on it, a lot of it, dried tacky and brown across his side — but underneath there is nothing to bleed from. Just a mark, a raised pink line the length of a fingernail, the kind you'd get from a childhood accident you can't remember. Angry and warm to the touch. And already old.
$name presses it. It gives slightly, like a bruise. Then it doesn't hurt at all.
He looks at the ring. Every mushroom in it is dead now, including the one at the centre, folded flat into the wet grass like something that has finished what it was doing.
He is on his feet and moving before he decides to be, up the bank and back onto the path and walking fast towards the road. It is only when he reaches the fence line, with the low orange light coming through the wire in long stripes, that he slows down and makes himself think about it properly.
He fell. He hit something on the way down — a stone, a broken branch; this wood is full of both. It bled a lot and looked worse than it was. He was out for an hour because he hit his head, and that is worth mentioning to somebody, eventually, when it won't turn into a whole thing.
By the time the streetlights come on he has almost made it fit.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
He gets in at ten past six. Jewelz is in the kitchen with the pan already on, and she looks at his shirt, and then at his face, and the phone comes down.
<<speech "Jewelz">>"What happened?"<</speech>>
<<speech "$name">>"I fell. Down a bank in the wood."<</speech>>
<<speech "Jewelz">>"Sit down. Let me see."<</speech>>
<<speech "$name">>"It's fine. It looked worse than it was — most of that's from one cut and it stopped ages ago."<</speech>>
<<speech "Jewelz">>"$name. Sit down."<</speech>>
He sits down. She gets his shirt up with the impatience of a woman who has dealt with worse from all three of them, and she stops.
<<speech "Jewelz">>"This is old."<</speech>>
<<speech "$name">>"It's from today."<</speech>>
<<speech "Jewelz">>"It's healed. There's a scar on it. $name, there's a scar."<</speech>>
<<speech "$name">>"I know what it looks like. I was there."<</speech>>
She looks at it a moment longer. Then she wets a cloth and cleans the dried blood off his side, and her hands are gentler than her voice ever is.
<<speech "Jewelz">>"You'll have hit your head. You're going to tell me if you feel sick in the night — not in the morning, in the night."<</speech>>
<<speech "$name">>"Fine."<</speech>>
<<speech "Jewelz">>"Say it properly."<</speech>>
<<speech "$name">>"I'll wake you up. I promise."<</speech>>
<<speech "Jewelz">>"Good. Because if you don't, I'll ring Melissa, and she'll be here inside twenty minutes with a casserole and an opinion, and she will take you to the hospital herself."<</speech>>
<<speech "$name">>"That's not a threat, that's just Melissa."<</speech>>
<<speech "Jewelz">>"It's a threat if you've got homework."<</speech>>
She goes back to the pan. Emily is in the doorway with her book held against her chest, having come to see what the noise was and stayed because she didn't want to interrupt. She doesn't say anything. She looks at his side, and at his face, and $name watches her decide not to ask — which is its own kind of answer about the house she grew up in.
<<speech "$name">>"I'm alright, Em. Genuinely. I fell over like an idiot."<</speech>>
<<speech "Emily">>"Okay."<</speech>>
She stays in the doorway anyway.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
<div style="text-align:center; margin:22px 0;"><img @src="window.getEventImagePath('Kali')" style="max-width:min(100%, 420px); width:100%; border-radius:8px; border:2px solid #3a2a4a; display:block; margin:0 auto;"><div style="color:#bd59ff; font-size:0.9em; margin-top:7px; font-weight:bold; letter-spacing:0.04em;">Kali</div></div>
<<charLink "kali" "Kali">> comes round at nine, the way she does most Saturdays.
She and Jewelz have been best friends since school — since before the parents died, since before any of it — and she works at the coffee place in town, which means she arrives smelling of coffee and carrying whatever didn't sell. Tonight it is four pastries in a paper bag, slightly squashed.
<<speech "Kali">>"They were going in the bin. Don't make a face at me, Jewelz, they were going in the actual bin."<</speech>>
<<speech "Jewelz">>"I didn't make a face."<</speech>>
<<speech "Kali">>"You made the face."<</speech>>
They end up at the kitchen table with the radio on low, and $name stays because Emily has gone up and the front room is cold. Kali has her boots off and her feet on the crossbar of Jewelz's chair, and she is describing a customer who complained about the temperature of a drink he had ordered iced. Jewelz is laughing in the tired way she laughs at the end of a week.
<<speech "Kali">>"So then he says — and he's serious, $name, he's completely serious — he says //is there a warm version of this//."<</speech>>
<<speech "$name">>"There is. It's called coffee."<</speech>>
<<speech "Kali">>"That's what I said! That is exactly what I said, and he asked for the manager."<</speech>>
She reaches across for the last pastry and her sleeve rides up and $name is looking at the inside of her wrist, and then the kitchen goes.
It does not fade or blur. It is simply replaced, whole, for something under two seconds.
<video src="img/Characters/Kali/Intro.mp4" width="100%" autoplay controls loop muted style="border-radius:6px; margin:14px 0;"></video>
Kali, on her back, and there is nothing coy about it — it is explicit and it is heavy and it is close enough that he can see the sweat on her collarbone. It comes with a physical weight, a pressure low in his stomach and a pull behind his eyes, and it has a texture he can only afterwards describe as //hunger//, except that hunger is a thing you have and this was a thing that had him.
Then the kitchen is back. The radio is still going. Kali has the pastry.
<<speech "Kali">>"— and I'm not even allowed to say anything, that's the worst part. Are you all right?"<</speech>>
<<speech "$name">>"Yeah."<</speech>>
<<speech "Kali">>"You went somewhere."<</speech>>
<<speech "$name">>"I'm tired. I fell over in the woods today and I think I hit my head."<</speech>>
<<speech "Jewelz">>"He did. He's got a scar he shouldn't have and he's promised to wake me if he's sick."<</speech>>
<<speech "Kali">>"A scar? From today?"<</speech>>
<<speech "$name">>"Apparently."<</speech>>
<<speech "Kali">>(interested, leaning over) "Let's see, then."<</speech>>
<<speech "$name">>"I'm not doing a viewing."<</speech>>
<<speech "Kali">>"Suit yourself. Jewelz, has he had a tetanus?"<</speech>>
<<speech "Jewelz">>"He's had a tetanus."<</speech>>
$name goes up before they've finished, which he never does, and he lies on his bed in his clothes with the light off.
He is nineteen. He has looked at Kali before — she has been in and out of this house since he was a child and he is not made of stone. That is not what happened. What happened had a beginning and an end and he was not driving it, and it arrived while she was talking about a customer and reaching for a pastry.
He puts it down to the head injury. That is a real thing that happens, he is fairly sure. People see things.
<div style="text-align:center; color:#3a2a4a; letter-spacing:0.5em; margin:26px 0;">◆</div>
It is only much later, with the house quiet and Kali's car long gone from the kerb, that $name puts his hand flat over the mark on his side and finds that it is warm. Warmer than the rest of him. It has been eight hours.
Under his palm, so faint he could talk himself out of it, something moves.
<div style="text-align:center; margin-top:32px;">[[That night (1)|Start2]]</div>
</div>