In-memory + optional file-backed logger.
The default logger when a user does Experiment(log=True). Stores every event
in a list so the UI / notebook can replay it afterwards, and optionally tees
each event to a JSON-lines file.
Cheap, thread-safe enough for single-process use (the event list uses a list append which is atomic in CPython), and dependency-free.