- Steam-linked login no longer writes literal "<null>" into the email field
(and no longer locks it read-only) when the verified identity has no email
- Login screen releases focus on app focus-out so the username caret stops
blinking while the window is inactive
- Calculator display text stays legible in light mode; the LCD-style panel
background is always dark, so its text should not follow the app theme
- Question player: gate the "save as flashcard" toolbar button behind
Brand.is_uat_environment(), matching the nav item, so it's hidden in prod
- Hide the discipline/system label while a question is unanswered so it
can't hint at the answer; reveal it once the explanation is shown
- Top-align question content instead of vertically centering it, with a
20px top margin, so it sits closer to the progress indicator
The RanaZe/STEP 3 TRAINER text block was top-aligned inside the
brand row's HBoxContainer, which is taller than the text due to the
190x190 icon beside it, so it hugged the top instead of centering
against the shield mark.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Wrapped the row in a CenterContainer so the checkbox+text sit centered
under the field column instead of hugging the left edge. Had to drop
the RichTextLabel's EXPAND_FILL (meaningless inside a CenterContainer,
which never stretches its child) in favor of an explicit 480px
minimum width - without one, the label collapsed toward zero width
and wrapped character-by-character, which is what the first attempt
at this actually rendered as before I caught it.
Verified with a direct coordinate check: the row's horizontal center
now matches the confirm-password field's center exactly (delta 0.0).
Root cause: CheckBox/Button reserves vertical space for a text
baseline even with an empty string, so no amount of custom_minimum_size
or stylebox content-margin tweaking produced a true square - it just
came out close-but-not-quite in some layouts and visibly elongated in
others.
Decoupled the visual square from the CheckBox entirely: a plain Panel
(exactly 20x20, toggled by direct click) now draws the border/fill,
while a real (invisible) CheckBox still holds .button_pressed for the
rest of the code to read. Also added left padding on the row and
vertically centered both the square and the consent text within it.
Verified with a direct size dump (20x20 in both checked/unchecked
states, where it previously measured non-square) and rendered
screenshots of both states.
The generic "style every Button" pass in _apply_theme also matched
CheckBox (it's a Button subtype) and ran after the checkbox-specific
styling, overwriting the intended blue border with the plain default
button box - and that box's own content margins were inflating the
checkbox well past its 26x26 minimum (actual rendered size was 60x52).
Skip CheckBox in that generic loop, zero out the checkbox stylebox's
content margins, shrink it to 22x22, and stop it stretching to the
row's full height. Also sized the consent text down (15->13) and gave
the row some vertical breathing room.
Verified with a rendered screenshot and a direct stylebox/size dump:
checkbox is now 22x24 with a real 2px blue border, matching the
provided reference.
Drop the bordered card - it wasn't the right direction. Instead:
- Plain small checkbox with just a blue border (no fill/icon when
unchecked), matching the reference exactly.
- "Terms of Service"/"Privacy Policy" render as inline blue links
within the sentence (RichTextLabel + BBCode [url], routed through
the same _open_legal_document as the footer), instead of a duplicate
link row underneath. meta_underlined = false to match the
reference's plain (non-underlined) link style.
Verified with real rendered screenshots at each step, including a
pixel-level crop confirming the underline was actually gone.
A bare CheckBox's word-wrap left-aligns every wrapped line flush with
the checkbox glyph, so "Privacy Policy." on its own line read as
unindented and sloppy next to an otherwise fully themed form. Split
the toggle from its label (a separate Label wraps within its own
column instead, so wrapped lines stay aligned under the first line)
and wrapped the row in a bordered card matching the app's field
styling. Clicking the label also toggles the checkbox now, for a
bigger hit target.
Verified with an actual rendered screenshot: wrapped text now indents
consistently, and both checked/unchecked states are legible.
Register and Steam-linking forms rendered their own Terms of
Service/Privacy Policy links right under the consent checkbox, on top
of the ones already pinned to the bottom of the panel. The consent
checkbox text alone is enough; the persistent footer covers the links.
Register, reset, and Steam-linking forms used a separate "Show
password" CheckButton row; the main login form already had the eye
icon embedded in the field itself. Generalized _add_password_reveal
(previously hardwired to a single tracked button) to support multiple
fields via password_reveal_entries, and used it for every password
field instead. Removed the now-unused _add_show_password.
Verified all 6 password fields (login, register x2, reset x2, steam)
get a working reveal button and there's no leftover "Show password"
checkbox anywhere.
Making the auth panel a fixed height (to kill the scrollbar) left the
shorter views (login, reset) stranded at the top with dead space below.
Split panel_content into a main_column (header, message, mode views -
expand-fill, center-aligned) and the legal footer as a sibling that
stays pinned to the panel's bottom edge regardless of which view is
showing or how tall its content is.
Verified headlessly: top/bottom whitespace above and below the active
view's content is now equal (e.g. login 174/174, steam 2/2), and the
footer's position doesn't move between modes.
The auth panel was a fixed 710x820 (640x790 on narrower desktop
windows) regardless of which view was showing, but Register and the
Steam linking form need up to ~990px to lay out without scrolling -
so the inner ScrollContainer was always kicking in for those views.
- Tightened form spacing (_new_form separation 16->10, field height
68->56, panel_content separation 24->16, page margins 56->28) to
shrink how much height each view actually needs.
- Size the panel to the tallest view's real requirement (1000/1010),
clamped to whatever height the window actually has so a short window
shrinks the panel - and lets the ScrollContainer take over as a
fallback - instead of the panel overflowing off-screen.
Verified headlessly across 1920x1080, 1366x768, and a narrow
compact-desktop width: no scrollbar in any mode at the two common
resolutions, and the panel now stays within the window (falling back
to scrolling only for the two tallest forms on the 768px-tall case,
rather than clipping off both edges of the screen as a fixed height
would have).
Steam uses a theme-aware monochrome glyph (light/dark variants) since
the button background flips between navy and white; Google keeps its
official 4-color mark, which reads fine on either background.