Fixed! Thank you for reporting, I missed that issue (tested on different browser)
I'm planning on a bigger writeup about it but basically I went with something I know well from my (non-gaming) work:
Almost all state tries to follow Domain Driven Dev rules: it is neatly divided into objects (Party, Character, Inventory, Equipment etc.) with strong encapsulation - so you cannot just call Character.Equipment[weapon] = sword but instead Character.Equip(sword, Party.Inventory) and Equip() does all the checks and updates to both Equipment and Inventory. This way I can call Equip() from wherever and be sure that state is correct. Really helps avoiding weird bugs.
The game logic is put into small "Scripts" classes: like MoveToAreaScript or GainItemScript etc. which can be queued together or easily call one another. This allows for easy reuse of pieces of logic - for example: GainItemScript will call Party.Inventory.Add and then DescribeScript to write 'You've gained X'.
Game story/script itself is a text file that is parsed into those "Scripts" - usually one line means one "Script" to be executed. It's also possible to define multiple Conditions for a given script (like HasItem, HasVisitedArea etc..)
Overall it works really well and the system is really flexible - maybe even bit too flexible. I started having some weird bugs coming from execution order of scripts etc. near the end of development when things got complex.