/* Hand-authored scenario frames, two or more per colour band. Each frame is a coherent, ready-to-run BPN: player-facing situation plus the GM's true pressure point and twist. The `contactArchetype` / `threatArchetype` fields are deliberately retained as a seam — a future NPC/monster module can read them to spin up stat blocks without this module owning any engine schema. */ export const FRAMES = { blue: [ { id: "blue-pump-clearance", shortTitle: "Pump Ghosts", missionFocus: "Eliminate a threat before it reaches public view.", colourMissionIdea: "Clear Carrien from a sewer pumping station before repair crews go live on-site.", location: "Sewer network and maintenance tunnels beneath a low-SCL tenement arc.", atmosphere: "Oppressive rain above ground, ankle-deep runoff below, and every tunnel echoing with machine throb.", opposition: "Carrien packs and one nest-alpha using the flooded access galleries.", oppositionAttitude: "Are starving, territorial, and driven to charge anything making light or noise.", civilianFaction: "Maintenance workers trying to keep the block from flooding into the hab levels.", extraObjective: "Recover one intact sample of the contamination feeding the nest.", escalationEvent: "If the pumps stay offline too long, the whole block begins to flood and civilians panic upward.", complication: "The maintenance foreman has been selling access schematics to scavengers and will try to hide it.", localTwist: "The contamination is not accidental; someone seeded the tunnels to force a redevelopment contract.", issuingDepartment: "Mort Department / Ops Control", contactRole: "Shift Maintenance Controller", contactArchetype: "controller", contactLocation: "A barricaded relay room overlooking the lower pump shafts.", threatArchetype: "carrien", threatRole: "Nest Alpha", threatCountLabel: "One alpha and a fast-moving pack." }, { id: "blue-eviction-cleanout", shortTitle: "Residue Notice", missionFocus: "Clean up an old SLA operational mess.", colourMissionIdea: "Evict squatters and secure a condemned recycler before demolition crews arrive.", location: "A half-powered recycling depot in a condemned housing strip.", atmosphere: "Chemical fog hangs low and the whole block stinks of hot metal, wet plaster, and old blood.", opposition: "A desperate street gang holding the depot plus a few terrified scavenger families inside the same shell.", oppositionAttitude: "Talk hard, posture for cameras, but are ready to fold if offered one way out.", civilianFaction: "Neighbourhood residents who want the gang gone but do not trust SLA to distinguish them from the problem.", extraObjective: "Keep the recycler's core machinery functional for sponsor inspection.", escalationEvent: "A scavenger fire starts in the upper catwalks, pushing everyone toward the same exit lanes.", complication: "The depot contains evidence from an earlier SLA kill-team visit that nobody filed correctly.", localTwist: "The original paperwork deliberately misclassified the site so a corporate shell company could seize it cheaply.", issuingDepartment: "Department-M / Internal Containment", contactRole: "Department-M Disposal Clerk", contactArchetype: "analyst", contactLocation: "A mobile command kiosk parked behind a portable blast shield.", threatArchetype: "ganger", threatRole: "Depot Gang Boss", threatCountLabel: "One loud boss and half a dozen badly coordinated shooters." } ], yellow: [ { id: "yellow-prototype-recovery", shortTitle: "Cold Return", missionFocus: "Retrieve an item or specimen intact.", colourMissionIdea: "Recover a stolen prototype before it disappears into the black-market chain.", location: "A transit interchange feeding into a hidden market spine.", atmosphere: "Packed concourses, vendor noise, flashing route boards, and too many bodies to easily track the courier.", opposition: "A retrieval crew working for organised crime with local route control and fast bikes on standby.", oppositionAttitude: "Would rather run than fight, but will kill witnesses if boxed in.", civilianFaction: "Black-market traders who know the unofficial routes and sell them to whoever pays first.", extraObjective: "Bring back the data case unopened and verifiably untampered.", escalationEvent: "The courier network triggers a station lockdown and reroutes all civilian flow through the kill zone.", complication: "The package is still broadcasting, making every interested party converge on the same target.", localTwist: "The prototype is bait; Head Office actually wants the retrieval crew followed back to a higher-value buyer.", issuingDepartment: "Cloak Tactical Oversight", contactRole: "Independent Financier", contactArchetype: "fixer", contactLocation: "A quiet cafe mezzanine overlooking the station's arrivals board.", threatArchetype: "retrieval-crew", threatRole: "Courier Handler", threatCountLabel: "One handler, two bike-runners, and a sniper looking after the exchange." } ], green: [ { id: "green-cannibal-perimeter", shortTitle: "Wall Bite", missionFocus: "Eliminate a threat before it reaches public view.", colourMissionIdea: "Hit a breach team before it can break through the Cannibal Sector perimeter and trigger a broadcast panic.", location: "The Cannibal Sector perimeter wall and the service roads wrapped around it.", atmosphere: "Sirens, floodlights, wet concrete, and the constant thump of distant impact on the wall plating.", opposition: "Cannibal raiders with improvised breaching charges and a local guide inside the city side.", oppositionAttitude: "Are committed, feral, and keen to take someone back with them if the breach fails.", civilianFaction: "A transient cluster of freight workers trapped near the service roads during lockdown.", extraObjective: "Capture one living raider who can identify the city-side collaborator.", escalationEvent: "A secondary breach warning forces Shiver units to peel away, leaving the squad exposed.", complication: "The internal guide is wearing a legitimate contractor pass and can blend into evac traffic.", localTwist: "The breach is a distraction for an unrelated extraction happening two gates away.", issuingDepartment: "Shiver Command Liaison Desk", contactRole: "Perimeter Shiver Sergeant", contactArchetype: "shiver", contactLocation: "An armoured checkpoint container bolted to the inner wall road.", threatArchetype: "raider", threatRole: "Breacher Chief", threatCountLabel: "A brutal lead breacher with a fast assault cell behind him." }, { id: "green-kill-order", shortTitle: "Dead Feed", missionFocus: "Hunt a named hostile and confirm status.", colourMissionIdea: "Stop a contract killer before the second murder finishes the media pattern.", location: "A rain-soaked rooftop district threaded with service bridges and maintenance lifts.", atmosphere: "Visibility is broken by rain, neon reflections, and intermittent drone spotlights.", opposition: "A professional killer with a two-person support team and pre-positioned escape routes.", oppositionAttitude: "Remain cool, efficient, and willing to trade casualties for a clean getaway window.", civilianFaction: "A cluster of thrill-streamers trying to capture the chase from nearby rooftops.", extraObjective: "Recover the killer's weapon package and comms slate intact.", escalationEvent: "The support team remotely kills the lights and forces the pursuit onto unsecured skybridges.", complication: "The target has a face the public already knows, making collateral narrative control much harder.", localTwist: "The supposed contract is only the visible layer; the true target is hidden among the responding authorities.", issuingDepartment: "Mort Department / Ops Control", contactRole: "Veteran Desk Op", contactArchetype: "detective", contactLocation: "A temporary command room in a shuttered rooftop transit office.", threatArchetype: "killer", threatRole: "Named Contract Killer", threatCountLabel: "One surgical hitter backed by two disciplined support shooters." } ], white: [ { id: "white-serial-pattern", shortTitle: "Witness Static", missionFocus: "Investigate a crime scene with political fallout.", colourMissionIdea: "Link a string of identical killings before the murderer reaches a protected witness.", location: "A residential block, its adjoining monorail stop, and the forensic seal around the newest murder scene.", atmosphere: "The block is unnaturally quiet, everyone is watching from behind cheap screens, and Shivers are over-managing the cordon.", opposition: "A serial killer cell staging scenes to manipulate a bigger investigation.", oppositionAttitude: "Enjoy the attention, leave deliberate clues, and want the squad to see the pattern too late.", civilianFaction: "Residents terrified of speaking after seeing just enough to know SLA is already late.", extraObjective: "Secure the witness and move them somewhere the killer cannot predict.", escalationEvent: "An old evidence trail suddenly points at a different scene and splits available manpower.", complication: "The witness's own statement is incomplete because they are protecting someone inside the block.", localTwist: "The killer is recreating an older SLA-blacklisted case and expects the same official cover-up.", issuingDepartment: "Mort Department / Ops Control", contactRole: "Case Liaison Detective", contactArchetype: "detective", contactLocation: "A sealed witness room improvised from a laundrette office.", threatArchetype: "killer", threatRole: "Pattern Cell Leader", threatCountLabel: "A lead killer with one cleanup partner and one obsessed documentarian." }, { id: "white-ammo-sabotage", shortTitle: "Spent Truth", missionFocus: "Retrieve data or recordings without contamination.", colourMissionIdea: "Trace sabotaged SLA ammunition back through the supply chain before anyone realises how deep it goes.", location: "A corporate ammo depot, a Shiver evidence locker, and a low-grade loading district in between.", atmosphere: "Power flickers every few minutes, loading servitors keep stuttering mid-task, and everybody is too tense to blink.", opposition: "Corporate security and one inside accountant trying to erase the trail before it reaches Head Office.", oppositionAttitude: "Prefer intimidation and paperwork pressure, but will switch to lethal containment if exposed.", civilianFaction: "Dock loaders who know the movement pattern of every crate but do not trust official investigators.", extraObjective: "Recover one clean crate and one tampered crate for comparison testing.", escalationEvent: "Depot lockdown procedures seal the archive level and begin deleting local logs.", complication: "The inside accountant is cooperating because their family is already off the board if they stop.", localTwist: "The sabotage was designed to make a specific squad fail publicly rather than to broadly poison supply.", issuingDepartment: "Department-M / Internal Containment", contactRole: "Corporate Asset Auditor", contactArchetype: "analyst", contactLocation: "A dark logistics office above the depot loading floor.", threatArchetype: "corpsec", threatRole: "Security Overseer", threatCountLabel: "One hard-edged overseer and a disciplined internal security team." } ], grey: [ { id: "grey-audit-escort", shortTitle: "Quiet Ledger", missionFocus: "Protect or escort a cargo asset.", colourMissionIdea: "Keep an audit convoy moving while everyone who profited from the missing cargo tries to erase the proof.", location: "An industrial spine road running between bonded warehouses and a secure internal archive.", atmosphere: "The sector is all sodium light, surveillance masts, and thin excuses from everyone in a suit.", opposition: "Departmentally protected smugglers, hired heavies, and one executive aide running the cover story.", oppositionAttitude: "Would rather pressure, delay, and redirect than openly trade fire in company view.", civilianFaction: "Warehouse staff who know something is wrong but fear losing the only stable work they have.", extraObjective: "Keep the audit chain unbroken from seizure to final archive.", escalationEvent: "A sponsor legal team arrives and tries to freeze the whole operation with paperwork.", complication: "The archive itself contains evidence implicating the issuing department.", localTwist: "The convoy is only half the story; the real theft walked out days ago wearing a department badge.", issuingDepartment: "Department-M / Internal Containment", contactRole: "Departmental Enforcement Liaison", contactArchetype: "corporate", contactLocation: "An armoured office container chained to the convoy lead truck.", threatArchetype: "corpsec", threatRole: "Internal Security Chief", threatCountLabel: "One security chief and a quiet detail of professional enforcers." } ], silver: [ { id: "silver-live-escort", shortTitle: "Smile Cut", missionFocus: "Protect or escort a person through a hostile district.", colourMissionIdea: "Keep a sponsor-backed public figure alive without letting the cameras see how close the job gets.", location: "A ribbon of sponsor venues, red-carpet choke points, and one ugly service corridor nobody told the cameras about.", atmosphere: "Flash lamps, branded drones, crowd heat, and just enough panic underneath the applause to be dangerous.", opposition: "A stalker cell, freelance agitators, and one rival sponsor fixer hoping to turn the event into a scandal.", oppositionAttitude: "Would prefer embarrassment over blood but are ready to escalate if the window closes.", civilianFaction: "Fans and paid attendees packed too tightly to separate cleanly from the real threat.", extraObjective: "Protect the sponsor narrative as much as the body being moved.", escalationEvent: "A live-feed malfunction dumps backstage footage into the public stream and sends the route sideways.", complication: "The VIP is hiding a personal agenda and keeps deviating from the protected path.", localTwist: "The entire appearance is bait designed to expose who inside the sponsor chain is leaking movement plans.", issuingDepartment: "Media Relations / Sponsor Operations", contactRole: "Media Fixer", contactArchetype: "media", contactLocation: "A mobile control booth hidden behind the main broadcast gantry.", threatArchetype: "security", threatRole: "Hostile Fixer", threatCountLabel: "One well-dressed operator with hired hands embedded in the crowd." } ], jade: [ { id: "jade-containment", shortTitle: "Wet Bloom", missionFocus: "Contain or quarantine an outbreak or Ebb event.", colourMissionIdea: "Lock down a contaminated block before the spill crosses into the transit grid.", location: "A mixed-use block connected to drainage canals and a damaged med-lab service annex.", atmosphere: "Filtered alarms, chemical stink, and a wet sheen on every surface that might be alive.", opposition: "Mutated survivors, a failed lab asset, and one containment officer already planning to burn the evidence.", oppositionAttitude: "Act unpredictably and spike between blind panic and sudden aggression.", civilianFaction: "A street clinic trying to keep the least infected residents alive long enough to evacuate.", extraObjective: "Secure one uncontaminated sample for Karma analysis.", escalationEvent: "Containment seals begin dropping floor by floor, isolating parts of the squad from one another.", complication: "The official quarantine map is wrong and funnels civilians toward the hottest zone.", localTwist: "The contamination profile matches a programme nobody admits still exists.", issuingDepartment: "Karma Hazard Response", contactRole: "Field Scientist", contactArchetype: "scientist", contactLocation: "A decontamination vestibule made from two bolted ambulance trailers.", threatArchetype: "stormer", threatRole: "Mutated Lab Asset", threatCountLabel: "One unstable asset and several contaminated survivors acting around it." } ], red: [ { id: "red-monorail-hostage", shortTitle: "Dead Platform", missionFocus: "Protect or escort a person through a hostile district.", colourMissionIdea: "Board a hijacked monorail, cut the threat out, and stop a public disaster before it multiplies.", location: "A moving monorail line, two sealed stations, and the service deck beneath the track.", atmosphere: "Screaming brakes, emergency klaxons, static over public address, and media drones already racing the train.", opposition: "A terror cell with improvised explosives and a hardline trigger operator.", oppositionAttitude: "Need the spectacle as much as the tactical win and will kill quickly if denied it.", civilianFaction: "Hostages trapped inside the train with just enough courage to help if guided correctly.", extraObjective: "Keep the train itself intact enough for a survivor extraction.", escalationEvent: "A secondary device threatens the inbound station and splits command priorities.", complication: "One hostage is secretly tied to the cell and is feeding them squad movement.", localTwist: "The train was chosen because someone important is riding under a false manifest.", issuingDepartment: "Shiver Command Liaison Desk", contactRole: "Transit Crisis Controller", contactArchetype: "controller", contactLocation: "A sealed signal room with live route telemetry and too many shouting department heads.", threatArchetype: "riot", threatRole: "Cell Trigger Man", threatCountLabel: "One detonation lead, two shooters, and a train full of leverage." }, { id: "red-broadcast-retake", shortTitle: "Signal Mercy", missionFocus: "Eliminate a threat before it reaches public view.", colourMissionIdea: "Retake a broadcast tower before the final message turns a bad district into a citywide panic.", location: "A media tower, its control floors, and the access streets packed with fleeing civilians.", atmosphere: "Emergency beacons, dropped live feeds, smoke in the ventilation stacks, and every screen in Mort pointing at the same problem.", opposition: "An extremist crew with tower access and stolen media credentials.", oppositionAttitude: "Expect to die but want the audience to watch it happen in the right order.", civilianFaction: "Panicking evacuees clogging the lower service roads and making every clean shot harder.", extraObjective: "Recover the message core and identify who green-lit tower access.", escalationEvent: "Backup transmitters spin up on a timer and broaden the threat window.", complication: "The tower engineer who can shut the system down has been wounded and hidden by the crowd.", localTwist: "The message is less propaganda than data dump, and one department in SLA wants it to air.", issuingDepartment: "Media Relations / Sponsor Operations", contactRole: "Broadcast Security Captain", contactArchetype: "shiver", contactLocation: "A lower-floor security post running on emergency battery.", threatArchetype: "security", threatRole: "Tower Seizure Lead", threatCountLabel: "One charismatic lead and a handful of committed technical shooters." } ], black: [ { id: "black-silent-vault", shortTitle: "Mute Entry", missionFocus: "Retrieve data or recordings without contamination.", colourMissionIdea: "Slip into a sealed vault, lift one file set, and leave the archive looking untouched.", location: "A corporate research vault buried under a routine logistics floor.", atmosphere: "Cold air, sound-dampened corridors, biometric locks, and too much silence to trust.", opposition: "Internal black security and one compartmentalised watcher who does not know the whole job.", oppositionAttitude: "Stay disciplined, silent, and willing to erase the evidence of their own failure.", civilianFaction: "Night-shift technicians who do not understand the stakes but know every route in the building.", extraObjective: "Remove a second innocuous-looking archive block that actually matters more than the main objective.", escalationEvent: "A silent alarm brings in an internal response team with orders to close the floor permanently.", complication: "The file set is mirrored to a live observer station and cannot simply be taken.", localTwist: "The client is not paying for the theft; they are paying to confirm what Head Office already suspects.", issuingDepartment: "Head Office Special Assignments", contactRole: "Darkfinder Case Officer", contactArchetype: "corporate", contactLocation: "A blackout-safe service apartment three blocks from the target tower.", threatArchetype: "blackops", threatRole: "Vault Warden", threatCountLabel: "One silent warden and a two-person ghost response team." }, { id: "black-disavowed-burn", shortTitle: "Ash Ledger", missionFocus: "Sabotage or destroy a target off the books.", colourMissionIdea: "Burn a deniable site and seed the right false evidence before anyone asks why it existed.", location: "A shell company warehouse wrapped around an unlisted lab basement.", atmosphere: "Generator hum, shuttered loading bays, and an air that already feels abandoned on purpose.", opposition: "Contract cleaners and one site supervisor prepared for a final-burn contingency.", oppositionAttitude: "Know the site is disposable and only care about buying enough time to erase the real trail.", civilianFaction: "Nearby dock crews who heard there was money in tonight's unusual overtime orders.", extraObjective: "Leave one trail leading toward a rival corporate culprit.", escalationEvent: "A chemical fire spreads faster than expected and starts opening parts of the hidden basement.", complication: "One asset inside the site is still alive and worth far more than the building.", localTwist: "The false evidence you were told to plant matches a previous cover story almost word for word.", issuingDepartment: "Head Office Special Assignments", contactRole: "Freelance Financier", contactArchetype: "fixer", contactLocation: "A remote comms booth patched through a dead sponsor office.", threatArchetype: "blackops", threatRole: "Cleanup Supervisor", threatCountLabel: "One hard cleanup lead, one torch specialist, and a final-burn team." } ], platinum: [ { id: "platinum-head-office", shortTitle: "Quiet Crown", missionFocus: "Protect or escort a person through a hostile district.", colourMissionIdea: "Extract a Head Office asset who knows too much without revealing the extraction is even happening.", location: "A sealed executive sector stitched into an older transit artery beneath it.", atmosphere: "Too clean above, too secret below, and everyone on-site acting as if the wrong word could kill them.", opposition: "A compartmentalised internal response team and one asset handler trying to rewrite the operation in real time.", oppositionAttitude: "Never shout, rarely miss, and assume everyone around them is expendable.", civilianFaction: "None officially, though a handful of overlooked service workers are trapped inside the machinery.", extraObjective: "Return every mission record to Head Office only.", escalationEvent: "Command changes the extraction route mid-run, implying compromise at the original pickup.", complication: "The protected asset is deciding whether the squad is the rescue team or the last cleanup team they will ever see.", localTwist: "The extraction itself is cover for a private conversation one Head Office director wants another never to hear.", issuingDepartment: "Head Office Special Assignments", contactRole: "Head Office Courier", contactArchetype: "corporate", contactLocation: "A private transit berth accessible only by dead-route credentials.", threatArchetype: "blackops", threatRole: "Executive Recovery Lead", threatCountLabel: "One elite retrieval leader and a pair of immaculate shadow operators." } ] }; export function framesForColour(key = "white") { return FRAMES[String(key ?? "white").toLowerCase()] ?? FRAMES.white; }