diff --git a/assets/icons/lucide/flask-conical.svg b/assets/icons/lucide/flask-conical.svg new file mode 100644 index 0000000..9a3fa9f --- /dev/null +++ b/assets/icons/lucide/flask-conical.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/assets/icons/lucide/flask-conical.svg.import b/assets/icons/lucide/flask-conical.svg.import new file mode 100644 index 0000000..193a804 --- /dev/null +++ b/assets/icons/lucide/flask-conical.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c2ud26rg3exo1" +path="res://.godot/imported/flask-conical.svg-f4d9011dce33718bd3c2a0f719a8656a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/lucide/flask-conical.svg" +dest_files=["res://.godot/imported/flask-conical.svg-f4d9011dce33718bd3c2a0f719a8656a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/icons/lucide/gem.svg b/assets/icons/lucide/gem.svg new file mode 100644 index 0000000..84dc964 --- /dev/null +++ b/assets/icons/lucide/gem.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/assets/icons/lucide/gem.svg.import b/assets/icons/lucide/gem.svg.import new file mode 100644 index 0000000..0ec162b --- /dev/null +++ b/assets/icons/lucide/gem.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://caty3viul0634" +path="res://.godot/imported/gem.svg-33acfe3fd8cfb097f65cc061d34abd2e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/lucide/gem.svg" +dest_files=["res://.godot/imported/gem.svg-33acfe3fd8cfb097f65cc061d34abd2e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/scripts/ui/main.gd b/scripts/ui/main.gd index ddf06cd..d7a1475 100644 --- a/scripts/ui/main.gd +++ b/scripts/ui/main.gd @@ -445,6 +445,7 @@ func _populate_navigation(container: VBoxContainer, include_brand: bool) -> void _add_nav_button(container, "donations", "Support RanaZe", "heart-pulse", true) _add_nav_button(container, "performance", "Profile", "user-round", true) _add_nav_button(container, "rz_store", "RZ Shop", "star", true) + _add_nav_button(container, "slot_machine", "Slot Machine", "gem", true) _add_nav_button(container, "settings", "Settings", "settings", true) _add_nav_button(container, "logout", "Log out", "log-out", true) @@ -489,6 +490,7 @@ func _on_navigation_pressed(key: String) -> void: "bookmarks": show_screen("bookmarks") "donations": show_screen("donations") "rz_store": show_screen("rz_store") + "slot_machine": show_screen("slot_machine") "logout": _logout() diff --git a/scripts/ui/navigation_routes.gd b/scripts/ui/navigation_routes.gd index 436406b..23d0a6e 100644 --- a/scripts/ui/navigation_routes.gd +++ b/scripts/ui/navigation_routes.gd @@ -32,5 +32,5 @@ static func key_for_screen(screen_name: String, payload: Variant = null) -> Stri elif screen_name == "rz_store": key = "rz_store" elif screen_name == "slot_machine": - key = "rz_store" + key = "slot_machine" return key diff --git a/scripts/ui/rz_slot_machine_screen.gd b/scripts/ui/rz_slot_machine_screen.gd index b54679d..daa801b 100644 --- a/scripts/ui/rz_slot_machine_screen.gd +++ b/scripts/ui/rz_slot_machine_screen.gd @@ -5,11 +5,13 @@ const STAR_ICON := preload("res://assets/icons/lucide/star.svg") const SHIELD_ICON := preload("res://assets/icons/lucide/shield.svg") const CLOCK_ICON := preload("res://assets/icons/lucide/clock-3.svg") const RESET_ICON := preload("res://assets/icons/lucide/rotate-ccw.svg") -const REEL_SYMBOLS := [STAR_ICON, SHIELD_ICON, CLOCK_ICON, RESET_ICON] +const GEM_ICON := preload("res://assets/icons/lucide/gem.svg") +const FLASK_ICON := preload("res://assets/icons/lucide/flask-conical.svg") +const REEL_SYMBOLS := [STAR_ICON, SHIELD_ICON, CLOCK_ICON, RESET_ICON, GEM_ICON, FLASK_ICON] const ICON_BY_REWARD_KEY := { "jackpot": "star", - "epic": "star", - "great": "star", + "epic": "gem", + "great": "shield", "exam_token": "clock-3", "qbank_reset": "rotate-ccw", "nice": "star", @@ -19,11 +21,13 @@ const ICON_BY_REWARD_KEY := { var main: Control var subtitle_label: Label -var back_button: Button var machine_panel: PanelContainer -var reel_icons: Array = [] +var reel_columns: Array = [] +var win_up_to_card: PanelContainer var win_up_to_label: Label +var cost_card: PanelContainer var cost_value_label: Label +var auto_card: PanelContainer var spin_button: Button var auto_spin_toggle: CheckButton var status_label: Label @@ -74,14 +78,6 @@ func on_show(_payload: Variant = null) -> void: func _build_header() -> void: - back_button = Button.new() - back_button.text = "← Back to Shop" - back_button.add_theme_font_override("font", Brand.font) - back_button.flat = true - back_button.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN - back_button.pressed.connect(func(): main.show_screen("rz_store")) - add_child(back_button) - var title := Label.new() title.text = "RZ Coin Slot Machine" title.add_theme_font_override("font", Brand.font) @@ -99,55 +95,93 @@ func _build_machine(parent: Control) -> void: var dark := UIThemeService.is_dark_mode() machine_panel = PanelContainer.new() machine_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL - machine_panel.add_theme_stylebox_override("panel", Brand.content_card_box(dark, true, Brand.ROYAL_BLUE)) + machine_panel.add_theme_stylebox_override("panel", _cabinet_box()) parent.add_child(machine_panel) var margin := MarginContainer.new() - margin.add_theme_constant_override("margin_left", 20) - margin.add_theme_constant_override("margin_right", 20) - margin.add_theme_constant_override("margin_top", 18) - margin.add_theme_constant_override("margin_bottom", 18) + margin.add_theme_constant_override("margin_left", 24) + margin.add_theme_constant_override("margin_right", 24) + margin.add_theme_constant_override("margin_top", 22) + margin.add_theme_constant_override("margin_bottom", 22) machine_panel.add_child(margin) var column := VBoxContainer.new() - column.add_theme_constant_override("separation", 14) + column.add_theme_constant_override("separation", 16) margin.add_child(column) - var reels_row := HBoxContainer.new() - reels_row.add_theme_constant_override("separation", 12) - reels_row.alignment = BoxContainer.ALIGNMENT_CENTER - column.add_child(reels_row) + _build_marquee(column) - reel_icons.clear() - for _i in range(3): - var reel_panel := PanelContainer.new() - reel_panel.custom_minimum_size = Vector2(84, 84) - reel_panel.add_theme_stylebox_override("panel", Brand.icon_circle_box(dark, Brand.ROYAL_BLUE, 12)) - var icon := TextureRect.new() - icon.texture = STAR_ICON - icon.modulate = Brand.AMBER - icon.custom_minimum_size = Vector2(40, 40) - icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE - icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED - icon.size_flags_horizontal = Control.SIZE_SHRINK_CENTER - icon.size_flags_vertical = Control.SIZE_SHRINK_CENTER - reel_panel.add_child(icon) - reels_row.add_child(reel_panel) - reel_icons.append(icon) + var reel_row := HBoxContainer.new() + reel_row.add_theme_constant_override("separation", 16) + reel_row.alignment = BoxContainer.ALIGNMENT_CENTER + column.add_child(reel_row) + var reel_screen := PanelContainer.new() + reel_screen.add_theme_stylebox_override("panel", _reel_screen_box()) + reel_row.add_child(reel_screen) + + var reel_margin := MarginContainer.new() + reel_margin.add_theme_constant_override("margin_left", 16) + reel_margin.add_theme_constant_override("margin_right", 16) + reel_margin.add_theme_constant_override("margin_top", 14) + reel_margin.add_theme_constant_override("margin_bottom", 14) + reel_screen.add_child(reel_margin) + + var reels_grid := HBoxContainer.new() + reels_grid.add_theme_constant_override("separation", 12) + reel_margin.add_child(reels_grid) + + reel_columns.clear() + for _column_index in range(3): + var reel_col := VBoxContainer.new() + reel_col.add_theme_constant_override("separation", 8) + reels_grid.add_child(reel_col) + var cells: Array = [] + for _row_index in range(3): + var icon := TextureRect.new() + icon.texture = STAR_ICON + icon.modulate = Brand.AMBER + icon.custom_minimum_size = Vector2(34, 34) + icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + reel_col.add_child(icon) + cells.append(icon) + reel_columns.append(cells) + + reel_row.add_child(_build_lever()) + + win_up_to_card = PanelContainer.new() + win_up_to_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false)) + column.add_child(win_up_to_card) + var win_margin := MarginContainer.new() + win_margin.add_theme_constant_override("margin_left", 14) + win_margin.add_theme_constant_override("margin_right", 14) + win_margin.add_theme_constant_override("margin_top", 10) + win_margin.add_theme_constant_override("margin_bottom", 10) + win_up_to_card.add_child(win_margin) win_up_to_label = Label.new() win_up_to_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER win_up_to_label.add_theme_font_override("font", Brand.font) win_up_to_label.add_theme_font_size_override("font_size", 15) win_up_to_label.add_theme_color_override("font_color", Brand.text_color(dark)) - column.add_child(win_up_to_label) + win_margin.add_child(win_up_to_label) var controls_row := HBoxContainer.new() - controls_row.add_theme_constant_override("separation", 14) + controls_row.add_theme_constant_override("separation", 12) column.add_child(controls_row) + cost_card = PanelContainer.new() + cost_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false)) + controls_row.add_child(cost_card) + var cost_margin := MarginContainer.new() + cost_margin.add_theme_constant_override("margin_left", 14) + cost_margin.add_theme_constant_override("margin_right", 14) + cost_margin.add_theme_constant_override("margin_top", 8) + cost_margin.add_theme_constant_override("margin_bottom", 8) + cost_card.add_child(cost_margin) var cost_box := VBoxContainer.new() cost_box.add_theme_constant_override("separation", 0) + cost_margin.add_child(cost_box) var cost_caption := Label.new() cost_caption.text = "Cost per spin" cost_caption.add_theme_font_override("font", Brand.font) @@ -159,19 +193,30 @@ func _build_machine(parent: Control) -> void: cost_value_label.add_theme_font_size_override("font_size", 15) cost_value_label.add_theme_color_override("font_color", Brand.text_color(dark)) cost_box.add_child(cost_value_label) - controls_row.add_child(cost_box) spin_button = Button.new() spin_button.text = "Spin" - spin_button.custom_minimum_size = Vector2(120, 44) + spin_button.custom_minimum_size = Vector2(140, 58) spin_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + spin_button.size_flags_vertical = Control.SIZE_SHRINK_CENTER spin_button.add_theme_font_override("font", Brand.font) + spin_button.add_theme_font_size_override("font_size", 17) _style_spin_button() spin_button.pressed.connect(_on_spin_pressed) controls_row.add_child(spin_button) + auto_card = PanelContainer.new() + auto_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false)) + controls_row.add_child(auto_card) + var auto_margin := MarginContainer.new() + auto_margin.add_theme_constant_override("margin_left", 14) + auto_margin.add_theme_constant_override("margin_right", 14) + auto_margin.add_theme_constant_override("margin_top", 8) + auto_margin.add_theme_constant_override("margin_bottom", 8) + auto_card.add_child(auto_margin) var auto_box := VBoxContainer.new() auto_box.add_theme_constant_override("separation", 0) + auto_margin.add_child(auto_box) auto_spin_toggle = CheckButton.new() auto_spin_toggle.text = "Auto Spin" auto_spin_toggle.add_theme_font_override("font", Brand.font) @@ -182,7 +227,6 @@ func _build_machine(parent: Control) -> void: auto_caption.add_theme_font_size_override("font_size", 11) auto_caption.add_theme_color_override("font_color", Brand.muted_color(dark)) auto_box.add_child(auto_caption) - controls_row.add_child(auto_box) var info_label := Label.new() info_label.text = "All rewards are instant and sent to your account." @@ -193,6 +237,80 @@ func _build_machine(parent: Control) -> void: column.add_child(info_label) +func _build_marquee(column: VBoxContainer) -> void: + var row := HBoxContainer.new() + row.alignment = BoxContainer.ALIGNMENT_CENTER + row.add_theme_constant_override("separation", 12) + column.add_child(row) + row.add_child(_marquee_star()) + var mark := Label.new() + mark.text = "RZ" + mark.add_theme_font_override("font", Brand.font) + mark.add_theme_font_size_override("font_size", 34) + mark.add_theme_color_override("font_color", Brand.SKY_BLUE) + row.add_child(mark) + row.add_child(_marquee_star()) + + +func _marquee_star() -> TextureRect: + var star := TextureRect.new() + star.texture = STAR_ICON + star.modulate = Brand.SKY_BLUE + star.custom_minimum_size = Vector2(16, 16) + star.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + star.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + return star + + +func _build_lever() -> Control: + var wrap := VBoxContainer.new() + wrap.alignment = BoxContainer.ALIGNMENT_BEGIN + wrap.size_flags_vertical = Control.SIZE_EXPAND_FILL + wrap.add_theme_constant_override("separation", 0) + + var knob := PanelContainer.new() + knob.custom_minimum_size = Vector2(22, 22) + knob.size_flags_horizontal = Control.SIZE_SHRINK_CENTER + var knob_box := StyleBoxFlat.new() + knob_box.bg_color = Brand.ROYAL_BLUE + knob_box.set_corner_radius_all(11) + knob_box.corner_detail = 20 + knob_box.anti_aliasing = false + knob.add_theme_stylebox_override("panel", knob_box) + wrap.add_child(knob) + + var rod := ColorRect.new() + rod.color = Color("64748b") + rod.custom_minimum_size = Vector2(5, 90) + rod.size_flags_horizontal = Control.SIZE_SHRINK_CENTER + wrap.add_child(rod) + + return wrap + + +func _cabinet_box() -> StyleBoxFlat: + var box := StyleBoxFlat.new() + box.bg_color = Color("0b1220") + box.border_color = Brand.SKY_BLUE + box.set_border_width_all(3) + box.corner_radius_top_left = 48 + box.corner_radius_top_right = 48 + box.corner_radius_bottom_left = 16 + box.corner_radius_bottom_right = 16 + box.shadow_color = Color(Brand.SKY_BLUE, 0.35) + box.shadow_size = 10 + return box + + +func _reel_screen_box() -> StyleBoxFlat: + var box := StyleBoxFlat.new() + box.bg_color = Color("e2e8f0") + box.border_color = Color("94a3b8") + box.set_border_width_all(2) + box.set_corner_radius_all(10) + return box + + func _build_rewards_panel(parent: Control) -> void: var dark := UIThemeService.is_dark_mode() var panel := PanelContainer.new() @@ -276,9 +394,11 @@ func _build_footer() -> void: func _refresh_theme_controls() -> void: var dark := UIThemeService.is_dark_mode() subtitle_label.add_theme_color_override("font_color", Brand.muted_color(dark)) - machine_panel.add_theme_stylebox_override("panel", Brand.content_card_box(dark, true, Brand.ROYAL_BLUE)) + win_up_to_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false)) win_up_to_label.add_theme_color_override("font_color", Brand.text_color(dark)) + cost_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false)) cost_value_label.add_theme_color_override("font_color", Brand.text_color(dark)) + auto_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false)) footer_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false)) footer_icon_panel.add_theme_stylebox_override("panel", Brand.icon_circle_box(dark, Brand.ROYAL_BLUE, 18)) footer_heading.add_theme_color_override("font_color", Brand.text_color(dark)) @@ -428,20 +548,23 @@ func _await_spin_result() -> Dictionary: func _animate_reels() -> void: - for index in range(reel_icons.size()): - _spin_one_reel(reel_icons[index], 0.9 + index * 0.25) + for index in range(reel_columns.size()): + _spin_one_reel(reel_columns[index], 0.9 + index * 0.25) -func _spin_one_reel(icon: TextureRect, duration: float) -> void: +func _spin_one_reel(cells: Array, duration: float) -> void: var elapsed := 0.0 var interval := 0.06 while elapsed < duration: - icon.texture = REEL_SYMBOLS[randi() % REEL_SYMBOLS.size()] + var symbol: Texture2D = REEL_SYMBOLS[randi() % REEL_SYMBOLS.size()] + for cell in cells: + cell.texture = symbol await get_tree().create_timer(interval).timeout elapsed += interval interval = minf(interval * 1.18, 0.22) - icon.texture = STAR_ICON - icon.modulate = Brand.AMBER + for cell in cells: + cell.texture = STAR_ICON + cell.modulate = Brand.AMBER func _play_coin_burst(coins_won: int) -> void: diff --git a/scripts/ui/rz_slot_machine_screen.gd.uid b/scripts/ui/rz_slot_machine_screen.gd.uid new file mode 100644 index 0000000..e2c086b --- /dev/null +++ b/scripts/ui/rz_slot_machine_screen.gd.uid @@ -0,0 +1 @@ +uid://col1hauyr27rn diff --git a/scripts/ui/rz_store_screen.gd b/scripts/ui/rz_store_screen.gd index a0688b6..f0231cf 100644 --- a/scripts/ui/rz_store_screen.gd +++ b/scripts/ui/rz_store_screen.gd @@ -28,10 +28,6 @@ var balance_value_label: Label var coin_caption_label: Label var inventory_label: Label var tab_controls: Array = [] -var banner_card: PanelContainer -var banner_icon_panel: PanelContainer -var banner_heading: Label -var banner_description: Label var section_heading: Label var section_subtitle: Label var products_grid: HFlowContainer @@ -53,7 +49,6 @@ func _ready() -> void: _build_header() _build_summary_card() _build_tabs() - _build_slot_machine_banner() section_heading = Label.new() section_heading.text = "Featured" @@ -222,63 +217,6 @@ func _apply_tab_theme(dark: bool) -> void: (entry["underline"] as ColorRect).color = Brand.ROYAL_BLUE if active else Color(0, 0, 0, 0) -func _build_slot_machine_banner() -> void: - var dark := UIThemeService.is_dark_mode() - banner_card = PanelContainer.new() - banner_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, true, Brand.ROYAL_BLUE)) - add_child(banner_card) - - var margin := MarginContainer.new() - margin.add_theme_constant_override("margin_left", 16) - margin.add_theme_constant_override("margin_right", 16) - margin.add_theme_constant_override("margin_top", 12) - margin.add_theme_constant_override("margin_bottom", 12) - banner_card.add_child(margin) - - var row := HBoxContainer.new() - row.add_theme_constant_override("separation", 14) - margin.add_child(row) - - banner_icon_panel = PanelContainer.new() - banner_icon_panel.custom_minimum_size = Vector2(40, 40) - banner_icon_panel.size_flags_vertical = Control.SIZE_SHRINK_CENTER - banner_icon_panel.add_theme_stylebox_override("panel", Brand.icon_circle_box(dark, Brand.ROYAL_BLUE, 20)) - var icon := TextureRect.new() - icon.texture = load("res://assets/icons/lucide/star.svg") - icon.custom_minimum_size = Vector2(20, 20) - icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE - icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED - icon.modulate = Brand.ROYAL_BLUE - banner_icon_panel.add_child(icon) - row.add_child(banner_icon_panel) - - var copy := VBoxContainer.new() - copy.size_flags_horizontal = Control.SIZE_EXPAND_FILL - copy.size_flags_vertical = Control.SIZE_SHRINK_CENTER - copy.add_theme_constant_override("separation", 2) - banner_heading = Label.new() - banner_heading.text = "RZ Coin Slot Machine" - banner_heading.add_theme_font_override("font", Brand.font) - banner_heading.add_theme_font_size_override("font_size", 15) - banner_heading.add_theme_color_override("font_color", Brand.text_color(dark)) - copy.add_child(banner_heading) - banner_description = Label.new() - banner_description.text = "Spend RZ Coins for a chance at bigger rewards." - banner_description.add_theme_font_override("font", Brand.font) - banner_description.add_theme_font_size_override("font_size", 12) - banner_description.add_theme_color_override("font_color", Brand.muted_color(dark)) - copy.add_child(banner_description) - row.add_child(copy) - - var play_button := Button.new() - play_button.text = "Play Now" - play_button.custom_minimum_size = Vector2(96, 36) - play_button.add_theme_font_override("font", Brand.font) - _style_buy_button(play_button) - play_button.pressed.connect(func(): main.show_screen("slot_machine")) - row.add_child(play_button) - - func _build_footer() -> void: var dark := UIThemeService.is_dark_mode() footer_card = PanelContainer.new() @@ -338,10 +276,6 @@ func _refresh_theme_controls() -> void: coin_caption_label.add_theme_color_override("font_color", Brand.muted_color(dark)) inventory_label.add_theme_color_override("font_color", Brand.muted_color(dark)) _apply_tab_theme(dark) - banner_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, true, Brand.ROYAL_BLUE)) - banner_icon_panel.add_theme_stylebox_override("panel", Brand.icon_circle_box(dark, Brand.ROYAL_BLUE, 20)) - banner_heading.add_theme_color_override("font_color", Brand.text_color(dark)) - banner_description.add_theme_color_override("font_color", Brand.muted_color(dark)) section_subtitle.add_theme_color_override("font_color", Brand.muted_color(dark)) footer_card.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false)) footer_icon_panel.add_theme_stylebox_override("panel", Brand.icon_circle_box(dark, Brand.ROYAL_BLUE, 18))