From 1ae62fe0db3d1d4a23400313b6831cbbf414f076 Mon Sep 17 00:00:00 2001 From: Phillip Tarrant Date: Tue, 14 Jul 2026 20:33:08 -0500 Subject: [PATCH] feat(creation): distinguish granted skills as owned, and enlarge the small text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- client/assets/theme/game_theme.tres | 78 +++++++++++++------ client/scenes/creation/CharacterCreation.tscn | 13 ++-- client/scripts/theme/build_game_theme.gd | 39 +++++++--- client/scripts/theme/theme_keys.gd | 4 +- .../scripts/ui/creation/character_creation.gd | 11 ++- 5 files changed, 101 insertions(+), 44 deletions(-) diff --git a/client/assets/theme/game_theme.tres b/client/assets/theme/game_theme.tres index 889c6fe..c4ad4de 100644 --- a/client/assets/theme/game_theme.tres +++ b/client/assets/theme/game_theme.tres @@ -504,9 +504,27 @@ corner_radius_top_right = 14 corner_radius_bottom_right = 14 corner_radius_bottom_left = 14 -[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nufy3"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nufy3"] +content_margin_left = 12.0 +content_margin_top = 6.0 +content_margin_right = 12.0 +content_margin_bottom = 6.0 +bg_color = Color(0.56078434, 0.41568628, 0.16470589, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.56078434, 0.41568628, 0.16470589, 1) +corner_radius_top_left = 14 +corner_radius_top_right = 14 +corner_radius_bottom_right = 14 +corner_radius_bottom_left = 14 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0d7vs"] +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_0d7vs"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_3fnfk"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2txdw"] content_margin_left = 12.0 content_margin_top = 6.0 content_margin_right = 12.0 @@ -522,7 +540,7 @@ corner_radius_top_right = 14 corner_radius_bottom_right = 14 corner_radius_bottom_left = 14 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_3fnfk"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_w7qkp"] content_margin_left = 12.0 content_margin_top = 6.0 content_margin_right = 12.0 @@ -538,7 +556,7 @@ corner_radius_top_right = 14 corner_radius_bottom_right = 14 corner_radius_bottom_left = 14 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2txdw"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rthnr"] content_margin_left = 12.0 content_margin_top = 6.0 content_margin_right = 12.0 @@ -554,9 +572,9 @@ corner_radius_top_right = 14 corner_radius_bottom_right = 14 corner_radius_bottom_left = 14 -[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_w7qkp"] +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ta3oh"] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rthnr"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ohwwq"] content_margin_left = 12.0 content_margin_top = 6.0 content_margin_right = 12.0 @@ -572,7 +590,7 @@ corner_radius_top_right = 14 corner_radius_bottom_right = 14 corner_radius_bottom_left = 14 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ta3oh"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ismtf"] content_margin_left = 12.0 content_margin_top = 6.0 content_margin_right = 12.0 @@ -588,7 +606,7 @@ corner_radius_top_right = 14 corner_radius_bottom_right = 14 corner_radius_bottom_left = 14 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ohwwq"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gs634"] content_margin_left = 12.0 content_margin_top = 6.0 content_margin_right = 12.0 @@ -615,15 +633,15 @@ Accent/font_sizes/font_size = 24 Accent/fonts/font = ExtResource("1_605w4") CardBody/base_type = &"Label" CardBody/colors/font_color = Color(0.41568628, 0.3529412, 0.22745098, 1) -CardBody/font_sizes/font_size = 13 +CardBody/font_sizes/font_size = 14 CardBody/fonts/font = ExtResource("2_4lwr2") CardTitle/base_type = &"Label" CardTitle/colors/font_color = Color(0.22745098, 0.18431373, 0.10980392, 1) -CardTitle/font_sizes/font_size = 19 +CardTitle/font_sizes/font_size = 20 CardTitle/fonts/font = ExtResource("2_4lwr2") Chip/base_type = &"Button" Chip/colors/font_color = Color(0.6039216, 0.56078434, 0.47058824, 1) -Chip/font_sizes/font_size = 11 +Chip/font_sizes/font_size = 12 Chip/fonts/font = ExtResource("3_eckwq") Chip/styles/focus = SubResource("StyleBoxEmpty_q5gpk") Chip/styles/hover = SubResource("StyleBoxFlat_bbpmc") @@ -631,7 +649,7 @@ Chip/styles/normal = SubResource("StyleBoxFlat_73lme") Chip/styles/pressed = SubResource("StyleBoxFlat_js3tr") ChosenTag/base_type = &"Label" ChosenTag/colors/font_color = Color(0.9411765, 0.9019608, 0.8156863, 1) -ChosenTag/font_sizes/font_size = 10 +ChosenTag/font_sizes/font_size = 11 ChosenTag/fonts/font = ExtResource("3_eckwq") ChosenTag/styles/normal = SubResource("StyleBoxFlat_ube3r") DarkPanel/base_type = &"PanelContainer" @@ -652,7 +670,7 @@ ItemTileEmpty/base_type = &"PanelContainer" ItemTileEmpty/styles/panel = SubResource("StyleBoxFlat_lw8lk") Mono/base_type = &"Label" Mono/colors/font_color = Color(0.6039216, 0.56078434, 0.47058824, 1) -Mono/font_sizes/font_size = 13 +Mono/font_sizes/font_size = 14 Mono/fonts/font = ExtResource("3_eckwq") ParchmentButton/base_type = &"Button" ParchmentButton/colors/font_color = Color(0.2901961, 0.24705882, 0.17254902, 1) @@ -677,16 +695,16 @@ PrimaryCard/base_type = &"PanelContainer" PrimaryCard/styles/panel = SubResource("StyleBoxFlat_najyk") PrimaryTag/base_type = &"Label" PrimaryTag/colors/font_color = Color(0.9411765, 0.9019608, 0.8156863, 1) -PrimaryTag/font_sizes/font_size = 9 +PrimaryTag/font_sizes/font_size = 10 PrimaryTag/fonts/font = ExtResource("3_eckwq") PrimaryTag/styles/normal = SubResource("StyleBoxFlat_jtb1k") RichTextLabel/colors/default_color = Color(0.2901961, 0.24705882, 0.17254902, 1) -RichTextLabel/font_sizes/normal_font_size = 20 +RichTextLabel/font_sizes/normal_font_size = 22 RichTextLabel/fonts/italics_font = ExtResource("4_i0b23") RichTextLabel/fonts/normal_font = ExtResource("2_4lwr2") SectionLabel/base_type = &"Label" SectionLabel/colors/font_color = Color(0.5411765, 0.46666667, 0.28235295, 1) -SectionLabel/font_sizes/font_size = 13 +SectionLabel/font_sizes/font_size = 14 SectionLabel/fonts/font = ExtResource("3_eckwq") SelectCard/base_type = &"Button" SelectCard/colors/font_color = Color(0.22745098, 0.18431373, 0.10980392, 1) @@ -701,25 +719,35 @@ SkillChip/colors/font_color = Color(0.3529412, 0.2627451, 0.14901961, 1) SkillChip/colors/font_disabled_color = Color(0.6627451, 0.5803922, 0.39215687, 1) SkillChip/colors/font_hover_color = Color(0.3529412, 0.2627451, 0.14901961, 1) SkillChip/colors/font_pressed_color = Color(0.9411765, 0.9019608, 0.8156863, 1) -SkillChip/font_sizes/font_size = 12 +SkillChip/font_sizes/font_size = 14 SkillChip/fonts/font = ExtResource("3_eckwq") SkillChip/styles/disabled = SubResource("StyleBoxFlat_onsig") SkillChip/styles/focus = SubResource("StyleBoxEmpty_gw0t7") SkillChip/styles/hover = SubResource("StyleBoxFlat_88l5g") SkillChip/styles/normal = SubResource("StyleBoxFlat_f8qac") SkillChip/styles/pressed = SubResource("StyleBoxFlat_u6gcs") +SkillChipGranted/base_type = &"Button" +SkillChipGranted/colors/font_color = Color(0.9411765, 0.9019608, 0.8156863, 1) +SkillChipGranted/colors/font_disabled_color = Color(0.9411765, 0.9019608, 0.8156863, 1) +SkillChipGranted/font_sizes/font_size = 14 +SkillChipGranted/fonts/font = ExtResource("3_eckwq") +SkillChipGranted/styles/disabled = SubResource("StyleBoxFlat_nufy3") +SkillChipGranted/styles/focus = SubResource("StyleBoxEmpty_0d7vs") +SkillChipGranted/styles/hover = SubResource("StyleBoxFlat_nufy3") +SkillChipGranted/styles/normal = SubResource("StyleBoxFlat_nufy3") +SkillChipGranted/styles/pressed = SubResource("StyleBoxFlat_nufy3") Tab/base_type = &"Button" Tab/colors/font_color = Color(0.41568628, 0.3529412, 0.22745098, 1) -Tab/styles/focus = SubResource("StyleBoxEmpty_nufy3") -Tab/styles/hover = SubResource("StyleBoxFlat_0d7vs") -Tab/styles/normal = SubResource("StyleBoxFlat_3fnfk") -Tab/styles/pressed = SubResource("StyleBoxFlat_2txdw") +Tab/styles/focus = SubResource("StyleBoxEmpty_3fnfk") +Tab/styles/hover = SubResource("StyleBoxFlat_2txdw") +Tab/styles/normal = SubResource("StyleBoxFlat_w7qkp") +Tab/styles/pressed = SubResource("StyleBoxFlat_rthnr") TabActive/base_type = &"Button" TabActive/colors/font_color = Color(0.9411765, 0.9019608, 0.8156863, 1) -TabActive/styles/focus = SubResource("StyleBoxEmpty_w7qkp") -TabActive/styles/hover = SubResource("StyleBoxFlat_rthnr") -TabActive/styles/normal = SubResource("StyleBoxFlat_ta3oh") -TabActive/styles/pressed = SubResource("StyleBoxFlat_ohwwq") +TabActive/styles/focus = SubResource("StyleBoxEmpty_ta3oh") +TabActive/styles/hover = SubResource("StyleBoxFlat_ohwwq") +TabActive/styles/normal = SubResource("StyleBoxFlat_ismtf") +TabActive/styles/pressed = SubResource("StyleBoxFlat_gs634") TitleKicker/base_type = &"Label" TitleKicker/colors/font_color = Color(0.6627451, 0.5176471, 0.24705882, 1) TitleKicker/font_sizes/font_size = 13 diff --git a/client/scenes/creation/CharacterCreation.tscn b/client/scenes/creation/CharacterCreation.tscn index 403f675..3dc65bb 100644 --- a/client/scenes/creation/CharacterCreation.tscn +++ b/client/scenes/creation/CharacterCreation.tscn @@ -145,7 +145,7 @@ layout_mode = 2 theme_override_constants/separation = 14 [node name="Race0" type="Button" parent="Split/Sheet/Body/RaceSection/Cards"] -custom_minimum_size = Vector2(0, 140) +custom_minimum_size = Vector2(0, 180) layout_mode = 2 size_flags_horizontal = 3 toggle_mode = true @@ -200,7 +200,7 @@ theme_type_variation = &"ChosenTag" text = "CHOSEN" [node name="Race1" type="Button" parent="Split/Sheet/Body/RaceSection/Cards"] -custom_minimum_size = Vector2(0, 140) +custom_minimum_size = Vector2(0, 180) layout_mode = 2 size_flags_horizontal = 3 toggle_mode = true @@ -255,7 +255,7 @@ theme_type_variation = &"ChosenTag" text = "CHOSEN" [node name="Race2" type="Button" parent="Split/Sheet/Body/RaceSection/Cards"] -custom_minimum_size = Vector2(0, 140) +custom_minimum_size = Vector2(0, 180) layout_mode = 2 size_flags_horizontal = 3 toggle_mode = true @@ -310,7 +310,7 @@ theme_type_variation = &"ChosenTag" text = "CHOSEN" [node name="Race3" type="Button" parent="Split/Sheet/Body/RaceSection/Cards"] -custom_minimum_size = Vector2(0, 140) +custom_minimum_size = Vector2(0, 180) layout_mode = 2 size_flags_horizontal = 3 toggle_mode = true @@ -774,9 +774,10 @@ toggle_mode = true theme_type_variation = &"SkillChip" text = "perception" -[node name="BonusRow" type="HBoxContainer" parent="Split/Sheet/Body/SkillSection"] +[node name="BonusRow" type="HFlowContainer" parent="Split/Sheet/Body/SkillSection"] layout_mode = 2 -theme_override_constants/separation = 10 +theme_override_constants/h_separation = 10 +theme_override_constants/v_separation = 8 [node name="Label" type="Label" parent="Split/Sheet/Body/SkillSection/BonusRow"] layout_mode = 2 diff --git a/client/scripts/theme/build_game_theme.gd b/client/scripts/theme/build_game_theme.gd index 9dd5664..94a4eeb 100644 --- a/client/scripts/theme/build_game_theme.gd +++ b/client/scripts/theme/build_game_theme.gd @@ -44,6 +44,7 @@ static func build_theme() -> Theme: _section_label(theme) _select_card(theme) _skill_chip(theme) + _skill_chip_granted(theme) _tags_and_primary(theme) _tiles(theme) _cards_and_panels(theme) @@ -98,7 +99,7 @@ static func _fonts(theme: Theme) -> void: # Mono chrome role. theme.set_type_variation(ThemeKeys.MONO, "Label") theme.set_font(&"font", ThemeKeys.MONO, load(MONO)) - theme.set_font_size(&"font_size", ThemeKeys.MONO, 13) + theme.set_font_size(&"font_size", ThemeKeys.MONO, 14) theme.set_color(&"font_color", ThemeKeys.MONO, Palette.MUTED_MONO) # Card type — the name + blurb inside a select-card. These sit ON PARCHMENT, so # they take INK, not CREAM. Godot's built-in default Label colour is WHITE, and a @@ -108,11 +109,11 @@ static func _fonts(theme: Theme) -> void: # title, 13px italic-serif #6a5a3a blurb.) theme.set_type_variation(ThemeKeys.CARD_TITLE, "Label") theme.set_font(&"font", ThemeKeys.CARD_TITLE, serif) - theme.set_font_size(&"font_size", ThemeKeys.CARD_TITLE, 19) + theme.set_font_size(&"font_size", ThemeKeys.CARD_TITLE, 20) theme.set_color(&"font_color", ThemeKeys.CARD_TITLE, Palette.INK_HEADING) theme.set_type_variation(ThemeKeys.CARD_BODY, "Label") theme.set_font(&"font", ThemeKeys.CARD_BODY, serif) - theme.set_font_size(&"font_size", ThemeKeys.CARD_BODY, 13) + theme.set_font_size(&"font_size", ThemeKeys.CARD_BODY, 14) theme.set_color(&"font_color", ThemeKeys.CARD_BODY, Palette.INK_MUTED) @@ -138,7 +139,7 @@ static func _rich_text(theme: Theme) -> void: # (the narration book, later quest briefs/dialogue) reads dark serif ink from here. theme.set_font(&"normal_font", "RichTextLabel", load(SERIF)) theme.set_font(&"italics_font", "RichTextLabel", load(SERIF_ITALIC)) - theme.set_font_size(&"normal_font_size", "RichTextLabel", 20) + theme.set_font_size(&"normal_font_size", "RichTextLabel", 22) theme.set_color(&"default_color", "RichTextLabel", Palette.INK_BODY) @@ -210,7 +211,7 @@ static func _chip(theme: Theme) -> void: theme.set_stylebox(&"pressed", k, _flat(Color(Palette.MUTED_MONO, 0.32), Palette.MUTED_MONO, 1, 3)) theme.set_stylebox(&"focus", k, StyleBoxEmpty.new()) theme.set_font(&"font", k, load(MONO)) - theme.set_font_size(&"font_size", k, 11) + theme.set_font_size(&"font_size", k, 12) theme.set_color(&"font_color", k, Palette.MUTED_MONO) @@ -219,7 +220,7 @@ static func _section_label(theme: Theme) -> void: # Mono's own colour is for dark surfaces; on parchment it needs the muted ink. theme.set_type_variation(ThemeKeys.SECTION_LABEL, "Label") theme.set_font(&"font", ThemeKeys.SECTION_LABEL, load(MONO)) - theme.set_font_size(&"font_size", ThemeKeys.SECTION_LABEL, 13) + theme.set_font_size(&"font_size", ThemeKeys.SECTION_LABEL, 14) theme.set_color(&"font_color", ThemeKeys.SECTION_LABEL, Palette.INK_LABEL_MUTED) @@ -250,13 +251,33 @@ static func _skill_chip(theme: Theme) -> void: theme.set_stylebox(&"disabled", k, _flat(Palette.PARCHMENT_INSET_2, Palette.PARCHMENT_BORDER_3, 1, 14)) theme.set_stylebox(&"focus", k, StyleBoxEmpty.new()) theme.set_font(&"font", k, load(MONO)) - theme.set_font_size(&"font_size", k, 12) + theme.set_font_size(&"font_size", k, 14) theme.set_color(&"font_color", k, Palette.INK_LABEL) theme.set_color(&"font_pressed_color", k, Palette.CREAM_BRIGHT) theme.set_color(&"font_hover_color", k, Palette.INK_LABEL) theme.set_color(&"font_disabled_color", k, Palette.PARCHMENT_BORDER_3) +static func _skill_chip_granted(theme: Theme) -> void: + # The FOURTH skill-chip state, split out of SkillChip's dim `disabled` look. A + # race-GRANTED skill (the elf already has perception) must read "you already have + # this" — OWNED — not "unavailable". So: a solid gold fill with cream text (the + # binding prefixes a ✓), where the pool-is-spent chips keep the plain dim disabled. + # It is inert like a disabled chip, so every interactive state paints the owned box. + var k := ThemeKeys.SKILL_CHIP_GRANTED + theme.set_type_variation(k, "Button") + var owned := _flat(Palette.INK_GOLD, Palette.INK_GOLD, 1, 14) + theme.set_stylebox(&"normal", k, owned) + theme.set_stylebox(&"hover", k, owned) + theme.set_stylebox(&"pressed", k, owned) + theme.set_stylebox(&"disabled", k, owned) + theme.set_stylebox(&"focus", k, StyleBoxEmpty.new()) + theme.set_font(&"font", k, load(MONO)) + theme.set_font_size(&"font_size", k, 14) + theme.set_color(&"font_color", k, Palette.CREAM_BRIGHT) + theme.set_color(&"font_disabled_color", k, Palette.CREAM_BRIGHT) + + static func _tags_and_primary(theme: Theme) -> void: # The two little flags that ride on a card's top edge, and the gold ring the # calling's primary attribute wears. Label takes a `normal` stylebox in Godot 4. @@ -264,14 +285,14 @@ static func _tags_and_primary(theme: Theme) -> void: theme.set_type_variation(chosen, "Label") theme.set_stylebox(&"normal", chosen, _pill(Palette.BLOOD, 5, 8, 3)) theme.set_font(&"font", chosen, load(MONO)) - theme.set_font_size(&"font_size", chosen, 10) + theme.set_font_size(&"font_size", chosen, 11) theme.set_color(&"font_color", chosen, Palette.CREAM_BRIGHT) var primary_tag := ThemeKeys.PRIMARY_TAG theme.set_type_variation(primary_tag, "Label") theme.set_stylebox(&"normal", primary_tag, _pill(Palette.INK_GOLD, 5, 9, 2)) theme.set_font(&"font", primary_tag, load(MONO)) - theme.set_font_size(&"font_size", primary_tag, 9) + theme.set_font_size(&"font_size", primary_tag, 10) theme.set_color(&"font_color", primary_tag, Palette.CREAM_BRIGHT) # The ability card in both states. It is NOT a plain ParchmentCard: it wears the PRIMARY diff --git a/client/scripts/theme/theme_keys.gd b/client/scripts/theme/theme_keys.gd index 5358793..0728c86 100644 --- a/client/scripts/theme/theme_keys.gd +++ b/client/scripts/theme/theme_keys.gd @@ -17,7 +17,8 @@ const PARCHMENT_CARD := &"ParchmentCard" const PARCHMENT_INSET := &"ParchmentInset" const DARK_PANEL := &"DarkPanel" const SELECT_CARD := &"SelectCard" # race/calling card: a Button whose `pressed` is CHOSEN -const SKILL_CHIP := &"SkillChip" # toggle: unpicked / picked / granted-so-inert +const SKILL_CHIP := &"SkillChip" # toggle: unpicked / picked / can't-pick-now (dim) +const SKILL_CHIP_GRANTED := &"SkillChipGranted" # a race-GRANTED skill: owned (gold + ✓), inert const CHOSEN_TAG := &"ChosenTag" # the little crimson "CHOSEN" flag const PRIMARY_TAG := &"PrimaryTag" # the little gold "PRIMARY" flag const PRIMARY_CARD := &"PrimaryCard" # the ability card ringed as the calling's primary @@ -85,6 +86,7 @@ const ALL := { DARK_PANEL: "PanelContainer", SELECT_CARD: "Button", SKILL_CHIP: "Button", + SKILL_CHIP_GRANTED: "Button", CHOSEN_TAG: "Label", PRIMARY_TAG: "Label", PRIMARY_CARD: "PanelContainer", diff --git a/client/scripts/ui/creation/character_creation.gd b/client/scripts/ui/creation/character_creation.gd index 10bd2bd..4739302 100644 --- a/client/scripts/ui/creation/character_creation.gd +++ b/client/scripts/ui/creation/character_creation.gd @@ -41,7 +41,7 @@ var _ability_cards: Array = [] @onready var _detail_mech: Label = $Split/Sheet/Body/CallingSection/Detail/Box/Mechanics @onready var _pool_row: HBoxContainer = $Split/Sheet/Body/SkillSection/PoolRow @onready var _pool_count: Label = $Split/Sheet/Body/SkillSection/PoolRow/Count -@onready var _bonus_row: HBoxContainer = $Split/Sheet/Body/SkillSection/BonusRow +@onready var _bonus_row: HFlowContainer = $Split/Sheet/Body/SkillSection/BonusRow @onready var _ability_row: HBoxContainer = $Split/Sheet/Body/AbilitySection/Cards @onready var _points: Label = $Split/Sheet/Body/AbilitySection/Head/Points @onready var _reroll: Button = $Split/Sheet/Body/AbilitySection/Head/Reroll @@ -225,11 +225,16 @@ func _bind_skills() -> void: chip.visible = false continue var skill: String = pool[i] + var granted := draft.is_granted(skill) chip.visible = true - chip.text = CreationCopy.skill_label(skill) + # A granted skill reads as OWNED (gold + ✓ via SkillChipGranted), not merely + # disabled — otherwise it looks identical to a "picks are spent" chip and reads + # as "unavailable" rather than "you already have this". + chip.theme_type_variation = ThemeKeys.SKILL_CHIP_GRANTED if granted else ThemeKeys.SKILL_CHIP + chip.text = ("✓ " + CreationCopy.skill_label(skill)) if granted else CreationCopy.skill_label(skill) chip.button_pressed = draft.is_picked(skill) # Inert when the race already granted it, or when the picks are spent. - chip.disabled = draft.is_granted(skill) or (not draft.is_picked(skill) and not draft.can_pick(skill)) + chip.disabled = granted or (not draft.is_picked(skill) and not draft.can_pick(skill)) _bonus_row.visible = draft.wants_bonus_skill() for i in range(_bonus_chips.size()):