Programmatic Theme builder + reusable popover and stepper widgets,
ported from CharacterCreator.zip's :root design tokens. Kitchen-sink
scene exercises every primitive for visual eyeballing.
CodexPalette.cs:
Color tokens lifted verbatim from the React prototype's `:root`
block (--bg, --ink, --gild, --seal, etc.). Variable names mirror
the CSS so the audit trail stays readable. Spacing locked at the
prototype's normal density (--gap=24, --pad=28, --radius=2).
Scope cut: only the Dark theme ships. The React prototype designed
Parchment, Dark, and Blood as switchable variations — user direction
during M5 is that only Dark (leather + candlelight) is wanted for
this game. Parchment/Blood code dropped, plan doc updated to match
(§1 goal #5, §4.5 UI map, §5 M5 scope, §10 resolved decisions #4).
No runtime theme switcher.
CodexTheme.Build():
Programmatically constructs a Godot Theme from CodexPalette.Dark
plus CodexSpacing/CodexType tokens. Configures Panel, Card,
CodexPopover styleboxes; Label variations for H1..H4, CodexTitle,
Eyebrow, Meta, ValidationOk/Error, CardName/Body/Meta, StepperNum/
Name; Button + PrimaryButton + GhostButton variants; LineEdit,
CheckBox, scrollbar styling.
Fonts: looks for CormorantGaramond / CrimsonPro / JetBrainsMono
TTFs in res://Fonts/ (or Content/Fonts/) and graceful-falls-back to
Godot defaults if missing. M5 ships with no fonts in repo; user can
drop them in later for typography parity with the React prototype.
CodexPopover.cs:
Hoverable text trigger + floating PanelContainer, mirrors
src/trait-hint.jsx. Viewport-clamps horizontally and vertically;
flips above the trigger if there's no room below; 80 ms grace
period when moving cursor from trigger to popover. Detriment
variant uses the seal-coloured stylebox. Future TraitName /
SkillChip / BonusPill widgets layer className differences on top.
CodexStepper.cs:
Roman-numeral horizontal stepper with Pending / Active / Complete /
Locked states. Active step gets a 2-px gild underline, Complete
shows a ✓ in seal-red, Locked shows ✕ + 0.45 modulate. Emits
StepClicked(int) for non-locked rows. M5 is decorative — M6 wires
the signal to the character-creation state machine.
KitchenSink.cs + Main.cs --codex-test:
Verification scene rendering every primitive (header, stepper,
buttons, inputs, cards, trait popovers). Clicks log to console.
Fonts default to Godot's Noto Sans until res://Fonts/ is populated.
Closes M5 of theriapolis-rpg-implementation-plan-godot-port.md.
Next: M6 (title + character creation).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>