init_colors() now survives a terminal rejecting every init_pair() call
(some serial-console terminfo entries claim start_color()/COLORS support
but can't actually set custom pairs), but that exposed a follow-on bug:
the list cursor and the cert-form Continue/Cancel buttons indicated
selection purely via the COLOR_SELECTED color pair, so once that pair
silently no-ops the current row/button becomes indistinguishable from
an unselected one. Add curses.A_REVERSE alongside the color pair for
the selected state — a plain video attribute that doesn't depend on
custom-pair support, so the cursor stays visible either way.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
curses.use_default_colors() raises on terminals (e.g. serial consoles
using TERM=linux/vt100) whose terminfo lacks default-color support;
init_colors() now falls back to an explicit black background and caps
the "disabled" color to 8-color terminals.
--reissue without --email silently sent no mail when the CN wasn't in
openvpncertupdate-metadata.json, even though its email was already
embedded in the cert's index.txt subject (via EASYRSA_REQ_EMAIL) and
the TUI already fell back to it. Since build_client_full() always
writes that subject field whenever an email is known, metadata.json
was a redundant, driftable copy — remove it and have get_email() read
index.txt directly, picking the last non-revoked entry for a CN since
index.txt can contain revoked/duplicate lines for the same CN.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Implement COLOR_* constants, initialization, box/centered drawing,
clamp utility, and InputField with handle_key/value logic for pure
text editing without live curses. All tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>