Create a Project - Bank Time - and create one Task per Employee where they can timesheet their hours in and out.
When they work more hours than required, they would reduce their hours for that day by logging a negative amount of hours on their bank time Task.
When the work less hours than required, they would increase their hours for that day by logging a positive amount of hours on their bank time Task.
A simple Automation Rule can update the Description of their bank time Task so they can see their "balance" at any time by clicking the Task during Timesheet Entry.
The Action is of type Update Record using Compute on the Description field:

'No hours available.' if record.effective_hours == 0 else ('%s hours available.' % str(-record.effective_hours) if record.effective_hours < 0 else 'No hours available - you owe %s hour(s).' % str(record.effective_hours))
User then manage their Timesheets like this:
Initially, when they click on their Bank Time Task:

They see:

When they reduce their worked hours from 9 to 8:

They would then see:

If they ever took more than available, they would see:

OPTIONAL: You may also want to schedule an Approval Activity for "withdrawals" of banked time, via another Automation Rule that looks for increases in the Time Spent field.