Keep in mind that one UTF8 character occupies up to 4 bytes, thus limiting the size of CHAR fields to 8,191 characters (32,767/4).
That is in para 3.5.1 of your link.
Yes. That means you can't define a CHAR(8192) or larger when your database character set is UTF-8.
( if you try to create something larger you get a "implementation limit exceeded" )
Note... if your character set is NONE or some ISO then you can go up to 32767 and although you can store UTF-8 in NONE fields, you'll get an error if the size exceeds the 8191.
I have read this. Also I've read https://www.firebirdsql.org/file/documentation/html/en/firebirddocs/firebirdinternals/firebird-internals.html
While it is not very exhaustive, I can imagine that for each new version of the record, VARCHARs were written with their actual length, i.e. the row is 'packed' and it is only with the significant data with it.
A nice snippet is here for showing the size of all fields:
(source
https://stackoverflow.com/a/69415593/1037511)
SELECT T.RDB$RELATION_NAME, RF.RDB$FIELD_NAME, RF.RDB$NULL_FLAG, F.RDB$FIELD_TYPE,
F.RDB$FIELD_LENGTH,
F.RDB$CHARACTER_LENGTH,
F.RDB$FIELD_LENGTH / RCS.RDB$BYTES_PER_CHARACTER AS calculated
FROM RDB$RELATIONS T
INNER JOIN RDB$RELATION_FIELDS RF
ON RF.RDB$RELATION_NAME = T.RDB$RELATION_NAME
INNER JOIN RDB$FIELDS F
ON F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE
LEFT JOIN RDB$CHARACTER_SETS RCS
ON RCS.RDB$CHARACTER_SET_ID = F.RDB$CHARACTER_SET_ID
WHERE T.RDB$VIEW_BLR IS NULL
AND (T.RDB$SYSTEM_FLAG IS NULL OR T.RDB$SYSTEM_FLAG = 0)
AND (RF.RDB$SYSTEM_FLAG IS NULL OR RF.RDB$SYSTEM_FLAG = 0)
ORDER BY T.RDB$RELATION_NAME, RF.RDB$FIELD_NAME
But why this doesn't apply for the CHARs too?
Well... that's just how CHAR works. Same as ansistring and string[10]. Why are they different?
They just are

Besides... for short strings like 1 or 2 characters, CHAR(1) is more efficient. They still have their purpose.
BTW. Don't forget Firebird didn't have a boolean type until recently, so you could use CHAR(1) DEFAULT 'T' CHECK (VALUE IN ('F','T')) NOT NULL for that.
I still have those as domain in my databases:
CREATE DOMAIN D_BOOLEAN_T AS CHAR(1) DEFAULT 'T' CHECK (VALUE IN ('F','T')) NOT NULL^
CREATE DOMAIN D_BOOLEAN_F AS CHAR(1) DEFAULT 'F' CHECK (VALUE IN ('F','T')) NOT NULL^
In practical terms consider just this one rule: only use CHARs if strings of few characters are to be stored; the exception to the rule being when working with intermediate tables that are required to export data to fixed length prn files. Then the fixed length field will be a positive advantage.
https://www.ibexpert.net/ibe/pmwiki.php?n=Doc.CHAR