DarkPanel is a PanelContainer-base variation (only a `panel`
stylebox); a Button looks up normal/hover/pressed, which don't exist
on it, so SystemDock's menu buttons rendered as default gray Godot
buttons instead of mock-faithful dark nav buttons.
Add a dedicated Button-base DockButton variation (Palette-only
colours, dock-dark normal/hover/pressed styleboxes), point
system_dock.gd's menu buttons at it, and regenerate the committed
game_theme.tres artifact from the builder.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep the design/logical canvas at 1920x1080 (charter §16 / mockups) but add a
window-size override so the window opens at 1600x900 and doesn't fill the whole
screen; canvas_items + keep-aspect scales the canvas to fit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two root causes behind the blank F6 run:
1. project.godot had no display/stretch config (README mandates canvas_items
@ 1920x1080). Added [display] window size + stretch mode/aspect — the
project's canvas foundation, needed by every screen.
2. A root Control run directly (F6) is not sized to the viewport by full-rect
anchors — it collapses to (0,0), clipping the ScrollContainer and hiding all
content. Size the root to the viewport explicitly and track size_changed
(dropping the full-rect anchors, which conflict with setting size directly).
Faithful main-scene run now measures root = scroll = viewport = 1920x1080.
Suite 125/125.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
palette.gd / theme_keys.gd already declare `class_name`, so `const Palette =
preload(...)` in every consumer shadowed the global class and emitted 4
editor errors ("has the same name as a global class"). Reference the global
class_names directly. Editor reload now clean; suite 125/125; runtime probe
still builds all 75 showcase nodes with the theme applied.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- build_game_theme.gd: extract build_theme() as a static func returning the
fully-built Theme; _init() is now a thin save+quit wrapper. Enables a test
to build a fresh Theme in memory without running the SceneTree main loop.
- test_theme_resource.gd: add test_committed_tres_matches_builder() — builds
a fresh Theme via the preloaded builder and compares bg_color against the
committed game_theme.tres for PrimaryCTA/normal, ParchmentCard/panel, and
DarkPanel/panel. Catches "palette/builder changed, .tres not regenerated."
- build_game_theme.gd: give Tab, TabActive, and Chip explicit hover/pressed/
focus styleboxes (focus is StyleBoxEmpty to suppress the default ring) so
they no longer fall back to Godot's default gray button on interaction.
Add a disabled stylebox + font_disabled_color to PrimaryCTA for the
unaffordable-CTA state the 2a shell will need.
- theme_keys.gd: add HEADING/ACCENT/MONO font-role consts (kept out of ALL,
which is stylebox-variation-only); build_game_theme.gd and
theme_showcase.gd now reference them instead of raw StringName literals.
- theme_showcase.gd: add an italic DM-voice RichTextLabel (EB Garamond
italic face, spec §6) and two semantic-coloured chips (BLOOD for
aggressive actions, GOLD for pay/faith) alongside the existing neutral
chip, demonstrating the script-applied colouring from spec §5.3.
- dark_bay.gdshader: comment noting the stripe uses FRAGCOORD (screen-space)
while the vignette uses UV (node-local) — intended for full-bleed use.
- surfaces/*.gd: ## comments documenting the accepted deviation from spec
§5.4 (uniforms set at runtime from Palette rather than baked into the
.tscn) — no behavior change.
- Regenerated game_theme.tres via build_game_theme.gd.
Full suite: 125/125 (was 124, +1 drift-guard test).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFDm1ku9WDUacK2S78m2be
- _surfaces(): add VignetteOverlay.tscn alongside ParchmentPanel/DarkBay,
backed by a Palette.STEEL ColorRect so the dim is visibly rendering.
- _variations(): add ItemTileEmpty (next to filled ItemTile), ParchmentInset,
and DarkPanel stylebox nodes.
- _fonts(): new section rendering default serif body, Accent
(Architects Daughter), and Mono (JetBrains Mono) labels at real sizes.
- _swatches(): wrap each ColorRect in a VBoxContainer with a Mono caption
Label naming its Palette const, per spec's "labelled swatches."
No raw hex / Color(...) literals introduced; all colour via Palette.*, all
styleboxes via ThemeKeys.* variation names.
By-hand cold-start test showed 3 phrases before the response; 1.5x the
cadence so each line stays on screen a touch longer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The throwaway harness hand-built a minimal canon log and left luck_descriptor
as the default "", which fails the canon-log schema (minLength 1) → /npc/speak
422s and the harness silently degrades to fallback. Build the player through
LogPlayer with a non-empty §7 fortune line. Verified: request now 200s and Fenn
answers in-voice.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Whole-branch review Minor #1: JSON.parse_string pushes an engine-level
error on a non-JSON body (e.g. a gateway HTML 502), which the project's
gutconfig promotes to a false failure — the same reason FallbackLibrary
already avoids it. Consistency fix; a non-JSON body still degrades.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Whole-branch review flagged that NewGame.construct validated class and
origin refs but not player.name. The canon-log schema requires
player.name with minLength:1, so a missing/blank name previously
returned ok:true and produced a log the API would reject with 422.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Also configure GUT to not treat push_error() as a test failure
(client/.gutconfig.json: failure_error_types = [engine, gut]).
The brief's LogPlayer/Quest setters intentionally push_error() on
rejected input; GUT's default failure_error_types includes
push_error, which would fail test_player_rejects_unknown_class and
test_quest_status_enum despite their assertions passing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>