If you want the program to:
- have a clear code,
- be relatively easy to expand later,
- have order in the source code,
you can use data containers that will store:
- working data, its content can be loaded from a file and also saved by the user to the file when the content of this container changes,
- auxiliary information, its content will not be saved after the program is closed.
The container from point 1, storing the actual data, could be a class (named e.g. TDataContainer), derived from TObject or TComponent, then it will be convenient to use in the code. It can have methods for cleaning its contents, saving data to a file, loading data from a file). It can also have properties properties used for changing (i.e. actual data) and properties informing about its state (read-only). This is part M of the MVC pattern, only simplified.
The container from point 2, storing auxiliary data could be a record (named e.g. TSession) or a simple class derived from TObject. It is intended only to exchange data between other objects. Its contents are to be lost when the program is closed.
Gradually (as the program develops), you can easily add the necessary properties, methods and events to them. This may seem complicated but in reality it is quite simple. It helps to keep the code simple and tidy. I have been using this approach for quite a long time.
---
EDIT:
You can also add a container that will be responsible for saving and reading program settings (named e.g. TSettings). It can also be implemented as a record or an object (e.g. TObject class). It can have methods for saving and reading program settings to/from an INI file (multi-platform) or the Registry (if the program will be used only on Windows).
Each of these containers would be used to store and exchange various information. Separating them into separate containers allows you to keep your code tidy.
What I would suggest avoiding is placing many simple variables in forms (a multitude of many variables of various simple types placed in different modules). As the program's source code becomes more and more extensive, this approach will be worse than plowing in a rocky field.
In the case of records, it is enough to declare them as a private field in the class of the main program window. To pass them to other windows (e.g. dialog windows), it is enough to pass a pointer to such a record. As 440bx suggests, using advanced records is a very good idea. Moreover, using them is practically covering 3/4 of the way towards OOP

Of course I prefer the object-oriented approach (classes), because I am irreversibly tainted by the "religion" of OOP

And in fact (no kidding), when the program code becomes more complex, classes really simplify further expansion. Some caution is required here: if the program is simple, there is no point in using OOP. This is profitable when the program will ultimately be expanded (I omit using the default Lazarus classes from the LCL library to create the GUI).