12 Commits

Author SHA1 Message Date
1ae62fe0db feat(creation): distinguish granted skills as owned, and enlarge the small text
Two F6-review follow-ups from the human's read of the running screen.

1. GRANTED skill chips now read as 'you already have this', not 'unavailable'.
   The elf's granted `perception` shared SkillChip's dim `disabled` look with the
   'picks are spent' chips, so it read as blocked. Split out a fourth state,
   SkillChipGranted — a solid gold fill, cream text, and a ✓ prefix (owned) — while
   the pool-is-spent chips keep the plain dim disabled. Applied per-chip in _bind_skills.

2. Enlarged the small mono/body/prose roles for readability on sub-1920 laptops
   (the 1920 design canvas scales DOWN on a smaller screen, so 11-13px text got
   tiny): DM prose 20->22, MONO 13->14, section labels 13->14, card title 19->20,
   card body 13->14, chips 11->12, skill chips 12->14, the two flag pills +1. Big
   serif headings unchanged.

   Two layout consequences the guards caught and I fixed, not silenced:
   - Race cards overflowed the taller blurb -> card min-height 140->180 (the overflow
     guard, which measures against the card the engine does NOT derive from the text,
     went red first; traps.md #17).
   - The 9-chip Human bonus row, wider at the bigger font, blew the whole sheet past
     the viewport -> BonusRow HBoxContainer -> HFlowContainer so it wraps instead of
     forcing the sheet wide. Nothing depends on the row's type (tests check child
     count + visibility only).

319 client tests green (theme drift guard + overflow guard included); screenshot-
verified at 1280x720: granted chip owned, no clipping, bonus row wraps cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 20:33:08 -05:00
63cbc8c16e fix(creation-screen): the white text, the badge on top of the roll, and a window too big for the laptop
The human's first F6 run found four defects headless GUT could not see, all
now fixed and break-proven.

1. Fifteen Labels shipped invisible. _fonts() sets a default font and size but
   never a default font_color for the base Label type, so a Label with no
   type-variation inherited Godot's built-in default — WHITE — and rendered
   white-on-parchment: the four race names, four race blurbs, and seven calling
   names, every unreadable string on the sheet. New CardTitle / CardBody roles
   (mock #3a2f1c / #6a5a3a) fix it. NOT a global default Label colour: the Title
   screen has 12 bare Labels on a dark background that rely on white.

2. The PRIMARY badge covered the rolled value. The ability card is a
   PanelContainer, and a Container force-fits its children, so the badge's
   authored anchors were dead letters — it stretched to the card's full width
   and centred over the value. Nesting it under a plain Control (not a
   Container) restores absolute positioning. The badges also carried _flat()'s
   12/6 card padding; a new tight pill stylebox matches the mock's 2px 9px.

3. Race cards overflowed their own border (108px card, 114px of content). Bumped
   to 140. The CHOSEN badge on the calling card moved from centre to the mock's
   top-right, and the ability card got its own AbilityCard variation with 16px
   top headroom for the badge (ParchmentCard is shared with the shell).

4. The default window (1600x900) was larger than a 1600x900 laptop's usable
   area, so the WM clamped it to 1589x752 and the run came up pillarboxed.
   Default is now 1280x720, resizable; the 1920x1080 design canvas is unchanged
   (canvas_items + keep scales it, so no layout number moved).

Also closes M4-b's two open copy items: the cutpurse origin fragment (it
contradicted its own blurb) and the Hint label (it omitted the roll's floor of
8, now pinned to NewGame.roll_attributes).

Guards for 1-4 are new and each was re-broken and watched go red. The overflow
guard in 3 was FIRST WRITTEN AS A TAUTOLOGY — Godot clamps Control.size up to
its combined minimum, so `min <= size` is `x <= x` — and passed against the bug,
29/29, until it was rewritten to measure against the card that clips. That is
traps.md #17 and the thirteenth cannot-fail assertion this branch has caught.

319 client tests green, content build green, theme drift guard satisfied.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 19:56:09 -05:00
0bbf94289a feat(theme): the creation screen's five variations
SelectCard (a Button whose `pressed` IS the chosen ring), SkillChip (a toggle
with unpicked/picked/granted-so-inert), the CHOSEN and PRIMARY tags, and the
gold PrimaryCard ring. Plus INK_LABEL_MUTED for the sheet's section headers.

Built by build_game_theme.gd and regenerated; the .tres is never hand-edited.
2026-07-13 14:48:17 -05:00
f07139256b feat(title): warm shader background, pulsing glow, drifting embers
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 10:54:22 -05:00
c6d513c966 feat(theme): TitleLogo + TitleKicker display variations
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 10:41:42 -05:00
6ef71aaa31 fix(shell): readable ink prose + uniform consumable tiles
The narration RichTextLabel had no theme styling, so it rendered near-white
and was unreadable on parchment. Add a base RichTextLabel style to the theme
(dark INK_BODY serif at 20px, italic face wired) — systemic and previews in
the editor; every parchment prose surface now reads as dark ink. Also clip
the consumable slot labels so a long name ("Antidote") can't stretch its tile
wider than the empty ones — all 8 stay a uniform 62px.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 09:47:21 -05:00
bca04e3a2e feat(theme): parchment Button variation for clickable parchment rows
ThemeKeys.PARCHMENT_CARD is a PanelContainer-base variation (only a
`panel` stylebox) — a Button looks up normal/hover/pressed/disabled,
which don't exist there, so a Button styled with it renders unskinned.
Add PARCHMENT_BUTTON, a Button-base variation with those four
styleboxes plus an empty focus box, built from Palette colours only.
Same fix pattern as DOCK_BUTTON for the system dock. Regenerated
game_theme.tres from the builder.
2026-07-11 09:07:16 -05:00
35c4586792 fix(shell): dark DockButton theme variation for the system dock
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>
2026-07-11 09:00:54 -05:00
6530625f4d fix(theme): drift-guard test, interactive stylebox states, ThemeKeys font consts, richer showcase (whole-branch review)
- 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
2026-07-10 20:59:05 -05:00
73fcf2d096 feat(theme): parchment/dark-bay/vignette shader surfaces as drop-in scenes
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 20:34:52 -05:00
9091707535 feat(theme): game_theme.tres (fonts + stylebox variations) via builder 2026-07-10 20:29:22 -05:00
3981047ec6 feat(theme): bundle EB Garamond, Architects Daughter, JetBrains Mono (OFL) 2026-07-10 20:25:06 -05:00