Add EMF field mode, Armory shop/waitlist, and ambient haunting layer

Three self-contained features, verified complete and cross-wired
end-to-end (audited: backend 54/54 tests, frontend 110/110 tests,
tsc --noEmit clean, i18n coverage script clean):

- EMF mode: DeviceMotion/DeviceOrientation-based field-meter sensing,
  a fifth séance channel alongside Wire/EVP/Radio/Ouija, with its own
  fragment prompt persona and full frontend gauge UI.
- Armory (shop/waitlist): pre-order capture page for the future
  Ultimate Quantum Box hardware line, rate-limited public endpoint,
  explicitly no payment collection.
- Haunting layer: ambient possession effects (dread-bed audio, title
  glitching, idle-paced whispers/manifests), respects
  prefers-reduced-motion, mounted once at the app root.

Plus WebUSB robustness fixes in lib/sdr.ts (Terratec vendor ID,
explicit selectConfiguration, isSecureContext gate).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013PphXq1s43DNRj1uWKGXof
This commit is contained in:
Indiana
2026-07-21 02:28:14 +00:00
parent c372427ced
commit 0756e677b9
33 changed files with 3148 additions and 48 deletions

View File

@@ -12,6 +12,7 @@
"nav": {
"home": "the threshold",
"codex": "codex",
"shop": "shop",
"seance": "séance",
"enter": "enter",
"logout": "depart"
@@ -27,6 +28,7 @@
"heroKicker": "an instrument for speaking with the dead bandwidth",
"cta": "BEGIN THE SÉANCE",
"ctaCodex": "browse the codex",
"ctaShop": "visit the armory",
"stats": {
"entities": "spirits catalogued",
"sessions": "séances held",
@@ -55,6 +57,11 @@
},
"featured": "most disturbed spirits",
"featuredEmpty": "the registry is still blank — be the first to disturb it",
"armory": {
"title": "HARDWARE FROM THE ARMORY",
"line": "the Ultimate Quantum Box is coming — a handheld séance instrument that makes the veil knock louder.",
"link": "enter the armory →"
},
"footer": "an interactive horror art installation — the spirits are fiction; the static is real",
"footerColophon": "self-hosted · no cloud · the veil runs on your machine"
},
@@ -77,7 +84,8 @@
"wire": "Wire Ghost",
"evp": "EVP",
"radio": "Spirit Radio",
"ouija": "Ouija"
"ouija": "Ouija",
"emf": "FIELD"
},
"passive": "passive listening",
"summon": "SUMMON",
@@ -132,14 +140,30 @@
"unsupportedTitle": "this vessel cannot hear the radio dead",
"unsupported": "Spirit Radio needs Chromium (WebUSB) and an RTL-SDR dongle. The other modes do not — the wire and the microphone still answer.",
"troubleshoot": "troubleshooting: chromium-based browser · udev rules for 0bda:2838 · the dongle plugged in, not merely believed in",
"insecure": "the radio dead only speak through consecrated ground — open this site via its https address.",
"insecureHint": "localhost counts as hallowed; a bare http://lan-ip does not.",
"noDevice": "no dongle answered the call",
"sweeping": "sweeping {{start}}–{{end}} MHz…",
"claimFailed": "the dongle refused to be claimed — is it in use elsewhere?"
"claimFailed": "the dongle refused to be claimed — is it in use elsewhere?",
"claimFix": "linux: the kernel driver dvb_usb_rtl28xxu is holding the dongle — `sudo modprobe -r dvb_usb_rtl28xxu` frees it until reboot (a udev rule banishes it for good). windows: swap the driver for WinUSB with Zadig.",
"tryAgain": "try again",
"errorTitle": "the static pushed back"
},
"ouija": {
"spelling": "the planchette spells",
"drift": "the planchette drifts, waiting for words — ask below, or summon."
},
"emf": {
"start": "raise the meter",
"stop": "ground the meter",
"calibrate": "calibrate",
"baseline": "resting field",
"listening": "feeling for disturbances in the field…",
"unsupportedTitle": "this vessel carries no field senses",
"unsupported": "a phone in your hand becomes the meter — this vessel has no motion senses to lend. open the veil on a phone, or let the other modes answer.",
"deniedTitle": "the field senses stay shut",
"denied": "this vessel refused its motion senses. grant motion access in your browser settings, then raise the meter again."
},
"entity": {
"title": "DOSSIER OF THE PRESENT",
"none": "no spirit summoned yet",
@@ -240,5 +264,92 @@
"empty": "no spirits match this filter — the registry keeps its secrets",
"back": "← back to the codex",
"notFound": "this spirit is not in the registry"
},
"shop": {
"back": "← the threshold",
"title": "THE ARMORY",
"subtitle": "instruments for those who would knock louder",
"flagship": {
"tag": "flagship instrument",
"name": "THE ULTIMATE QUANTUM BOX",
"desc": "An ESP32-P4/C6 handheld séance instrument — thermal camera, EMF whisker array, geophone, spirit-box mic preamp and a little OLED face that stares back. It signs into the same Quantumancy account you already haunt and unlocks the hardware-driven modes of this site: thermal apparition maps, vibration anomaly feeds, calibrated EMF.",
"specs": {
"thermal": "thermal camera",
"emf": "EMF whisker array",
"geophone": "geophone",
"mic": "spirit-box mic preamp",
"oled": "OLED display"
},
"price": "est. $249 — pre-order"
},
"modulesTitle": "MODULES THAT KNOCK",
"unlocksLabel": "unlocks:",
"modules": {
"emfArray": {
"name": "EMF Whisker Array",
"desc": "a bouquet of multi-axis field sensors, sniffing the air for intentions",
"unlocks": "a richer, calibrated FIELD mode",
"price": "est. $59 — pre-order"
},
"geophone": {
"name": "Geophone Puck",
"desc": "hears footsteps in rooms where nobody is standing",
"unlocks": "the vibration anomaly feed",
"price": "est. $49 — pre-order"
},
"spiritMic": {
"name": "Spirit Mic Preamp",
"desc": "lowers the noise floor so the whispering comes through cleaner",
"unlocks": "cleaner EVP captures",
"price": "est. $69 — pre-order"
},
"uvIlluminator": {
"name": "UV/IR Illuminator",
"desc": "paints the dark in spectrums the living were never meant to see",
"unlocks": "night séances + camera work",
"price": "est. $39 — pre-order"
}
},
"interests": {
"quantumBox": "the Ultimate Quantum Box",
"emfArray": "EMF Whisker Array",
"geophone": "Geophone Puck",
"spiritMic": "Spirit Mic Preamp",
"uvIlluminator": "UV/IR Illuminator"
},
"waitlist": {
"title": "THE MANIFEST",
"desc": "leave an address and an obsession — when the first boxes ship, we reach through to the names on this list first",
"emailLabel": "email address",
"emailPlaceholder": "you@somewhere.in.the.static",
"interestLabel": "interest",
"submit": "join the manifest",
"pending": "carving your name…",
"listed": "you are on the manifest — we will reach through when the boxes ship",
"alreadyListed": "you are already on the manifest",
"invalid": "that address does not reach us",
"crowded": "the veil is crowded — try again later",
"error": "something stirred in the static — your name was not carved"
},
"honesty": "the Ultimate Quantum Box is in active development — this is a reservation manifest, no payment is taken. the website works fully without it; hardware only knocks louder."
},
"haunting": {
"whisper": {
"behindYou": "behind you",
"cold": "cold",
"stay": "stay",
"seesYou": "it sees you",
"closer": "closer",
"stillHere": "still here",
"lineListening": "the line is listening",
"dontLook": "don't look",
"beneathStatic": "beneath the static",
"knockTwice": "knock twice"
},
"title": {
"seesYou": "QUANTUMANCY — it sees you",
"behindYou": "QUANTUM▓NCY — behind you",
"listening": "…listening…"
}
}
}