ClubHud.razor

The club hub UI for a football career game, rendered as a Razor panel. Draws the nav bar, home overview, squad pitch with drag and drop lineup, bench, league table and fixtures, cup brackets, missions, training upgrade workbench, kit and ball selection, player catalog, plus several developer art and card review pages.

Messy Code
@using Sandbox
@using Sandbox.UI
@using Socer
@using System
@using System.Linq
@using System.Globalization
@inherits PanelComponent

<root @ref="ClubRoot" class="@(Game?.ClubOpen==true ? "shown" : "hidden") @(Game?.ClubPage=="Главная"?"home-screen":"") @(Game?.ClubPage=="Состав"?"squad-screen":"") @(Game?.TutorialStep>=0?$"tour-active tour-step-{Game.TutorialStep}":"") @GamePreferences.TextSizeClass @(PackRevealActive?"pack-cinema-open":"")">
@if(Game?.Career is not null)
{
    @if(Game.QuickBroadcastOpen)
    {
        <QuickMatchBroadcast Game="@Game" />
    }
    else
    {
    <div class="club-nav @(Game.PreparingMatch?"preparation-hidden":"")">
        @foreach(var page in new[]{"Главная","Лига","Кубок","Missions","Карточки","Catalog"})
        { var clubPage=page=="Главная"; <button class="@((Game.ClubPage==page || (clubPage && Game.ClubPage is "Состав" or "Тренировки" or "Equipment"))?"chosen":"") club-page-@(NavKey(page))" onclick=@(()=>NavigateClubPage(page))><span class="nav-icon-ai ai-@(NavKey(page))"></span><label>@NavName(page)</label>@if(page=="Missions" && C.ClaimableMissions+C.ClaimableCareerRewards>0){<span class="mission-badge">@(C.ClaimableMissions+C.ClaimableCareerRewards)</span>}</button> }
        <div class="spacer"></div>
        <div class="nav-wallets localized-text"><div class="nav-wallet"><span class="nav-icon-ai ai-coins"></span><label>@($"{C.Coins:N0}")</label></div><div class="nav-wallet nav-cup-wallet"><span class="nav-icon-ai ai-cup-token"></span><label>@($"{C.CupTokens:N0}")</label></div></div>
        <button class="resume-match" disabled="@(Game.QuickMatchRunning || Game.MatchModeSelection || (Game.Match.Seconds<=0 && !C.HasCompleteLineup))" onclick=@(()=>Game.ResumeMatch())><span class="nav-icon-ai ai-play"></span><label>@(C.Pending!=null?"Return to match":"Watch match")</label></button>
        @if(C.Pending==null && !C.CupWindow) { <button class="friendly" onclick=@(()=>Game.PrepareFriendly())><span class="nav-icon-ai ai-ball"></span><label>Friendly</label></button> }
    </div>
    @if(C.HasRelegationChoice)
    {
        <button class="relegation-pending localized-text" onclick=@(()=>Game.OpenRelegationChoice())><span class="nav-icon-ai ai-ball"></span><div><label>@StoreText("Вылет из лиги","Relegation")</label><label>@StoreText("Выберите штраф или проведите матч медиа-лиги, чтобы продолжить сезон.","Choose the fine or coach a Media League match to continue the season.")</label></div><label>@StoreText("Выбрать →","Choose →")</label></button>
    }
    @foreach(var completing in C.Tournaments.Where(t=>t.WorldCompletionPending))
    {
        var completionCup=completing;
        bool failed=!string.IsNullOrEmpty(completing.WorldCompletionError);
        <div class="cup-world-status @(failed?"failed":"") localized-text">
            <span class="nav-icon-ai ai-cup"></span>
            <div><label>@completing.Name</label><label>@(failed?StoreText("Не удалось досчитать оставшиеся матчи. Ваш результат сохранён — можно повторить расчёт.","The remaining matches could not be completed. Your result is saved; retry the calculation."):StoreText("Другие клубы доигрывают сетку. Лига доступна; следующий сезон откроется после финала.","Other clubs are completing the bracket. League play is available; the next season opens after the final."))</label></div>
            @if(failed){<button class="cup-world-retry" onclick=@(()=>Game.RetryCupWorldCompletion(completionCup.Id))>@StoreText("Повторить расчёт","Retry calculation")</button>}
            else{<label class="cup-world-progress">@StoreText("Рассчитываем…","Calculating…")</label>}
        </div>
    }
    @if(Game.PreparingMatch)
    {
        <div class="prematch-strip"><div><label class="eyeline">@($"BEFORE THE MATCH · {C.TeamName(0)} / {Game.PreparationOpponent}")</label><label class="prematch-title">Your starting eleven</label><label class="muted">Choose a formation and drag players into position. Then choose how to follow the match.</label></div><button class="preview-opponent" onclick=@(()=>InspectUpcoming())>View opponent</button><button class="cancel-lineup" onclick=@(()=>Game.CancelPreparation())>Back</button><button class="primary confirm-lineup" disabled="@(!C.HasCompleteLineup)" onclick=@(()=>Game.ConfirmPreparation())>CONTINUE TO MATCH →</button></div>
    }
    else if(Game.ClubPage is "Главная" or "Состав" or "Тренировки" or "Equipment")
    {
        <div class="team-subnav">
            <button class="team-overview @(Game.ClubPage=="Главная"?"chosen":"")" onclick=@(()=>Game.ClubPage="Главная")><span class="nav-icon-ai ai-overview"></span><label>Overview</label></button>
            <button class="team-squad-view @(Game.ClubPage=="Состав"?"chosen":"")" onclick=@(()=>Game.ClubPage="Состав")><span class="nav-icon-ai ai-squad"></span><label>Squad and formation</label></button>
            <button class="team-player-training @(Game.ClubPage=="Тренировки"?"chosen":"")" onclick=@(()=>Game.ClubPage="Тренировки")><span class="nav-icon-ai ai-training"></span><label>Upgrades</label></button>
            <button class="team-equipment @(Game.ClubPage=="Equipment"?"chosen":"")" onclick=@(()=>Game.ClubPage="Equipment")><span class="nav-icon-ai ai-kit"></span><label>Kits &amp; balls</label></button>
            @if(SocerDeveloper.ShowNavigation){<button class="open-football-lab localized-text" onclick=@(()=>Game.RunFootballLab("dribble",nextSeed:true))><span class="nav-icon-ai ai-ball"></span><label>@StoreText("Лаборатория · DEV","Football lab · DEV")</label></button>}
        </div>
    }
    <div data-club-page="@Game.ClubPage" class="club-body @(Time.Now-PageEnteredAt<.08f?"page-entering":"page-ready")">
    @if(Game.ClubPage=="Главная")
    {
        var next=Upcoming;var standing=C.Standings().First(r=>r.Team==0);
        <div class="club-overview">
            <div class="club-identity-panel">
                <img class="identity-crest" src="@C.TeamCrest(0)" />
                <label class="identity-name">@C.TeamName(0)</label><label class="eyeline">@($"SEASON {C.Season}")</label>
                <div class="club-vitals"><div><label class="vital-value">@TeamRating</label><label>SQUAD RATING</label></div><div><label class="vital-value">@($"{C.FilledSlots}/11")</label><label>STARTING XI</label></div></div>
                <button class="primary overview-squad" onclick=@(()=>Game.ClubPage="Состав")><span class="nav-icon-ai ai-squad"></span><label>@(C.HasCompleteLineup?"Manage squad":"Complete your starting XI")</label></button>
                <div class="overview-cup-history">
                    <div class="cup-history-heading"><label class="eyeline">@(GamePreferences.Russian?"РЕЗУЛЬТАТЫ КУБКОВ":"CUP RESULTS")</label><button onclick=@(()=>NavigateClubPage("Кубок"))>@(GamePreferences.Russian?"Все →":"All →")</button></div>
                    @foreach(var result in C.CupResults.Take(3)){<div class="cup-history-row @(result.PlaceFrom==1?"champion":"")"><div><label class="cup-history-name">@result.CupName</label><label class="cup-history-season">@(GamePreferences.Russian?$"Сезон {result.Season}":$"Season {result.Season}")</label></div><label class="cup-history-place">@CupPlace(result)</label></div>}
                    @if(!C.CupResults.Any()){<label class="cup-history-empty">@(GamePreferences.Russian?"Здесь появятся итоги завершённых кубков.":"Completed cup runs will appear here.")</label>}
                </div>
            </div>
            <div class="overview-main">
                <div class="overview-match">
                    <div class="overview-match-heading"><label class="eyeline">@(C.DueCup?.Name??"NEXT MATCH")</label><label class="muted localized-text">@(C.HasRelegationChoice?StoreText("ОЖИДАЕТ РЕШЕНИЯ","AWAITING YOUR CHOICE"):next!=null?(GamePreferences.Russian?$"Тур {next.Round}":$"Round {next.Round}"):StoreText("СЕЗОН ЗАВЕРШЁН","SEASON COMPLETE"))</label></div>
                    @if(C.HasRelegationChoice)
                    {
                        <label class="overview-season-end localized-text">@StoreText("Клуб потерял доход после вылета","Relegation reduced club income")</label><button class="primary relegation-open localized-text" onclick=@(()=>Game.OpenRelegationChoice())>@StoreText("Штраф или медиа-лига →","Fine or Media League →")</button>
                    }
                    else if(next!=null)
                    {
                        <div class="overview-faceoff"><div><img src="@C.TeamCrest(0)" /><label>@C.TeamName(0)</label></div><label class="overview-vs">VS</label><div><img src="@C.FixtureTeamCrest(next,Opponent(next))" /><label>@C.FixtureTeamName(next,Opponent(next))</label></div></div>
                        <div class="overview-match-actions"><button class="primary hub-play" onclick=@(()=>PlayUpcoming())><span class="nav-icon-ai ai-play"></span><label>@(C.Pending!=null?"Resume match":"Play match")</label></button><button onclick=@(()=>InspectUpcoming())>View opponent</button></div>
                        @if(!C.HasCompleteLineup){<label class="lineup-warning">Fill all 11 positions before starting a match.</label>}
                    }
                    else{<label class="overview-season-end">Season complete</label><button class="primary" disabled="@(!C.SeasonComplete)" onclick=@(()=>Game.NewSeason())>Next season →</button>}
                </div>
                <CareerFinaleView Career="@C" OnOpenCup="@(()=>OpenCup(C.FinalCup))" />
                <div class="overview-competition-row">
                    <button class="overview-competition league-screen [email protected]" onclick=@(()=>Game.ClubPage="Лига")><div class="league-emblem large"><label>@LeagueMark(C.Division)</label><span></span></div><div class="overview-league-copy"><label class="eyeline">@LeagueName(C.Division)</label><b>@($"#{Place} · {standing.Points} PTS")</b><label>@($"{standing.Played}/{C.LeagueRoundCount} matches")</label></div><label class="tile-arrow">→</label></button>
                </div>
                <div class="overview-results"><div class="match-history-heading"><label class="eyeline">RECENT RESULTS</label><button class="open-match-history localized-text" onclick=@(()=>{ArchiveListOpen=true;ArchivePage=0;})>@StoreText("История матчей →","Match history →")</button></div><div class="overview-results-list">
                    @foreach(var f in RecentResults)
                    {
                        <div class="overview-result report-result" onclick=@(()=>ShowMatchReport(f))><div class="overview-result-team @(f.Home==0?"our-club":"")"><img src="@C.FixtureTeamCrest(f,f.Home)" /><label>@C.FixtureTeamName(f,f.Home)</label></div><div class="overview-result-score @ResultClass(f)"><b>@($"{f.HomeGoals} : {f.AwayGoals}")</b>@if(f.Penalties){<label>@(GamePreferences.Russian?$"пен. {f.HomePenalties}:{f.AwayPenalties}":$"PEN {f.HomePenalties}:{f.AwayPenalties}")</label>}</div><div class="overview-result-team @(f.Away==0?"our-club":"")"><img src="@C.FixtureTeamCrest(f,f.Away)" /><label>@C.FixtureTeamName(f,f.Away)</label></div></div>
                    }
                    @if(!RecentResults.Any()){<label class="muted">Your club story begins at the first whistle.</label>}
                </div></div>
            </div>
        </div>
    }
    else if(Game.ClubPage=="Тренировки")
    {
        @if(!C.Cards.Any(p=>!p.IsAcademyLoan))
        {
            <div class="upgrade-empty-roster localized-text"><label>@StoreText("Нет игроков для улучшения","No players to upgrade")</label><label>@StoreText("Получите постоянного футболиста из пака. Временных игроков академии нельзя улучшать. Если инвентарь заполнен, спишите ненужную карточку ниже, чтобы освободить место для пака.","Find a permanent player in a pack. Temporary academy players cannot be upgraded. If inventory is full, discard an unwanted card below to make space for a pack.")</label><button onclick=@(()=>NavigateClubPage("Карточки"))>@StoreText("Перейти к пакам →","Go to packs →")</button>
                <div class="training-filters"><label>@StoreText("Ваши карточки","Your cards")</label><button class="@(TrainingGrade==0?"chosen":"")" onclick=@(()=>SetTrainingGrade(0))>@StoreText("Все","All")</button>@for(int j=1;j<=3;j++){var grade=j;<button class="training-grade-@j @(TrainingGrade==j?"chosen":"")" onclick=@(()=>SetTrainingGrade(grade))>@TrainingGradeName(j)</button>}</div>
                <div class="training-card-shelf"><div class="training-card-list">@foreach(var item in TrainingCards){var cardItem=item;<div class="training-inventory-entry"><ClubItemCardView Training="@item" Disabled="@UpgradeBusy" CssClass="@($"training-inventory-card training-item-{item.Id} {(TrainingItemId==item.Id?"item-selected":"")}")" OnSelected="@(()=>ChooseTrainingCard(cardItem))" /></div>}@if(!TrainingCards.Any()){<label>@StoreText("Карточек этого качества пока нет.","No cards of this quality.")</label>}</div></div>
                <div class="training-inventory-pages"><button class="training-page-prev" disabled="@(UpgradeBusy || EffectiveTrainingPage==0)" onclick=@(()=>ChangeTrainingPage(-1))>←</button><label>@TrainingPageLabel</label><button class="training-page-next" disabled="@(UpgradeBusy || EffectiveTrainingPage+1>=TrainingPageCount)" onclick=@(()=>ChangeTrainingPage(1))>→</button></div>
                @if(ActiveTraining!=null)
                {
                    <div class="training-discard-controls"><label>@TrainingItemLabel(ActiveTraining)</label>
                    @if(TrainingDiscardItemId==ActiveTraining.Id){<label class="training-discard-warning">@StoreText("Списать эту карточку навсегда? Монеты и другие предметы не возвращаются.","Discard this card permanently? No coins or other items are refunded.")</label><div><button class="training-discard-cancel" onclick=@CancelTrainingDiscard>@StoreText("Оставить карточку","Keep card")</button><button class="training-discard-confirm" disabled="@(!CanDiscardTraining)" onclick=@ConfirmTrainingDiscard>@StoreText("Списать 1 карточку","Discard 1 card")</button></div>}
                    else{<button class="training-discard-request" disabled="@(!CanDiscardTraining)" onclick=@RequestTrainingDiscard>@StoreText("Списать выбранную…","Discard selected…")</button>}
                    </div>
                }
            </div>
        }
        else
        {
        <div class="squad-page academy">
            <div class="academy-top">
                <div class="training-hero">
                    <label class="training-title localized-text">@StoreText("Улучшения игрока","Player upgrades")</label>
                    <div class="training-podium @(TrainingGlow?"upgrade-arriving":"")"><div class="podium-ring"></div><PlayerCardView Card="@UpgradeDisplayPlayer" ClubSeed="@C.ClubSeed" HighlightSkill="@(TrainingGlow?GrantedUpgrade.Skill:UniqueSkill.None)" CssClass="@("academy-card "+(TrainingGlow?"trained":""))" /></div>
                    <label class="athlete-name">@Selected.Name</label><label class="athlete-role">@($"{PlayerPositions.Card(Selected)} · {(GamePreferences.Russian?UiRussian.Translate(Selected.Country):Selected.Country)} · {(GamePreferences.Russian?UiRussian.Translate(Selected.Rarity):Selected.Rarity)}")</label>
                    <LegendaryAbilityView Card="@Selected" Compact="@(true)" />
                    <div class="upgrade-capacity localized-text"><label>@StoreText("Скиллы","Skills")</label><div>@for(int i=0;i<UniqueSkills.MaxSlots(Selected);i++){<span class="@(i<UpgradeDisplayPlayer.SkillLoadout.Count?"filled":"")"></span>}</div><label>@($"{UpgradeDisplayPlayer.SkillLoadout.Count}/{UniqueSkills.MaxSlots(Selected)}")</label></div>
                    <label class="training-feedback localized-text">@StoreText("Наведите на значок скилла, чтобы узнать его эффект.","Hover a skill badge to see its effect.")</label>
                </div>
                <div class="training-workbench">
                    <div class="upgrade-workbench-scroll">
                    <div class="workbench-heading localized-text"><label class="section-title">@StoreText("Карточки улучшений","Upgrade cards")</label><label class="muted">@C.TrainingInventory.Count</label><button class="open-skill-library" onclick=@(()=>SkillLibraryOpen=true)>@StoreText("Список скиллов","Skill library")</button></div>
                    <div class="upgrade-stage upgrade-stage-@TrainingAnimation localized-text">
                        <div class="upgrade-card-action">
                            <div class="upgrade-card-socket">
                            @if(UpgradeVisualTraining!=null){<div class="upgrade-consumption @(TrainingAnimation==1?"consuming":TrainingAnimation==2?"spent":"")"><ClubItemCardView Training="@UpgradeVisualTraining" CssClass="upgrade-selected-card" Disabled="@(true)" /></div>}
                            else{<div class="upgrade-card-placeholder"><img src="/ui-icons/plus.svg" /></div>}
                            </div>
                            <button class="primary apply-training-card @(UpgradeReplacesSkill?"replaces-skill":"")" disabled="@(!CanApplyTraining)" onclick=@ApplyTraining><label>@(UpgradeBusy?StoreText("Применяется…","Applying…"):UpgradeReplacesSkill?StoreText("Заменить случайный скилл","Replace a random skill"):StoreText("Добавить скилл","Add a skill"))</label></button>
                        </div>
                        @if(TrainingAnimation==1){<div class="upgrade-stage-copy"><label class="upgrade-stage-title">@StoreText("Карточка расходуется…","Using your card…")</label><label class="muted">@StoreText("Игрок получает новый скилл","A new skill is on its way")</label><div class="upgrade-charge"><span></span></div></div>}
                        else if(TrainedPlayer==Selected.Id && GrantedUpgrade!=null && ActiveTraining==null){<div class="upgrade-received [email protected] @(TrainingGlow?"revealing":"")"><div class="upgrade-received-heading"><SkillBadgeView Skill="@GrantedUpgrade.Skill" Grade="@GrantedUpgrade.Grade" CssClass="upgrade-received-icon" /><div><label class="upgrade-received-caption">@(PreviousUpgrade==null?StoreText("Новый скилл!","New skill!"):StoreText("Скилл заменён!","Skill rerolled!"))</label><label class="upgrade-received-name">@UniqueSkills.Name(GrantedUpgrade.Skill,GamePreferences.Russian)</label><label class="upgrade-received-grade">@UniqueSkills.GradeName(GrantedUpgrade.Grade,GamePreferences.Russian)</label></div></div><label class="upgrade-received-effect">@UniqueSkills.EffectDescription(GrantedUpgrade,GamePreferences.Russian)</label>@if(PreviousUpgrade!=null){<label class="upgrade-previous">@StoreText("Вместо: ","Replaces: ")@UniqueSkills.SkillName(PreviousUpgrade,GamePreferences.Russian)</label>}</div>}
                        else{<div class="upgrade-stage-copy"><label class="upgrade-stage-title">@(ActiveTraining==null?StoreText("Выберите карточку ниже","Choose a card below"):UpgradeReplacesSkill?StoreText("Случайная замена скилла","Reroll a random skill"):StoreText("Новый случайный скилл","A new random skill"))</label><label class="upgrade-stage-description">@(UpgradeReplacesSkill?StoreText("Один случайный скилл будет заменён другим. Остальные сохранятся.","One random equipped skill changes to another. The others stay."):StoreText("Откройте ещё один скилл для этого игрока.","Unlock another skill for this player."))</label>
                        @if(UpgradeGoldAtRisk){<div class="upgrade-reroll-warning"><div class="upgrade-warning-mark"><label>!</label></div><label>@StoreText("Золотой скилл тоже может замениться обычным. Отменить замену нельзя.","A gold skill can be replaced by a normal one. This cannot be undone.")</label></div>}
                        @if(ActiveTraining!=null){<div class="upgrade-odds"><div><span class="odds-normal"></span><label>@StoreText($"Обычный {100-UniqueSkills.UpgradeGoldChance(ActiveTraining)}%",$"Normal {100-UniqueSkills.UpgradeGoldChance(ActiveTraining)}%")</label></div><div><span class="odds-gold"></span><label>@StoreText($"Золотой {UniqueSkills.UpgradeGoldChance(ActiveTraining)}%",$"Gold {UniqueSkills.UpgradeGoldChance(ActiveTraining)}%")</label></div></div><label class="upgrade-use-note">@StoreText("Расходуется 1 карточка · без повторов скиллов","Uses 1 card · no duplicate skills")</label>}</div>}
                    </div>
                    <div class="training-filters localized-text"><label>@StoreText("Ваши карточки","Your cards")</label><button class="@(TrainingGrade==0?"chosen":"")" onclick=@(()=>SetTrainingGrade(0))>@(GamePreferences.Russian?"Все":"All")</button>@for(int j=1;j<=3;j++){var grade=j;<button class="training-grade-@j @(TrainingGrade==j?"chosen":"")" onclick=@(()=>SetTrainingGrade(grade))>@TrainingGradeName(j)</button>}</div>
                    <div class="training-card-shelf"><div class="training-card-list">@foreach(var item in TrainingCards){var cardItem=item;<div class="training-inventory-entry"><ClubItemCardView Training="@item" Disabled="@UpgradeBusy" CssClass="@($"training-inventory-card training-item-{item.Id} {(TrainingItemId==item.Id?"item-selected":"")}")" OnSelected="@(()=>ChooseTrainingCard(cardItem))" /></div>}@if(!TrainingCards.Any()){<div class="training-empty"><img src="/ui-icons/ui-bold-nav-store.svg" /><label class="localized-text">@(C.TrainingInventory.Count==0?StoreText("Карточки улучшений выпадают из паков.","Find upgrade cards in packs."):StoreText("Карточек этого качества пока нет.","No cards of this quality."))</label></div>}</div></div>
                    <div class="training-inventory-pages localized-text"><button class="training-page-prev" disabled="@(UpgradeBusy || EffectiveTrainingPage==0)" onclick=@(()=>ChangeTrainingPage(-1))>←</button><label>@TrainingPageLabel</label><button class="training-page-next" disabled="@(UpgradeBusy || EffectiveTrainingPage+1>=TrainingPageCount)" onclick=@(()=>ChangeTrainingPage(1))>→</button></div>
                    <label class="training-reason localized-text">@TrainingReason</label>
                    </div>
                    @if(ActiveTraining!=null)
                    {
                        <div class="training-discard-controls localized-text"><label>@TrainingItemLabel(ActiveTraining)</label>
                        @if(TrainingDiscardItemId==ActiveTraining.Id){<label class="training-discard-warning">@StoreText("Списать эту карточку навсегда? Монеты и другие предметы не возвращаются.","Discard this card permanently? No coins or other items are refunded.")</label><div><button class="training-discard-cancel" onclick=@CancelTrainingDiscard>@StoreText("Оставить карточку","Keep card")</button><button class="training-discard-confirm" disabled="@(!CanDiscardTraining)" onclick=@ConfirmTrainingDiscard>@StoreText("Списать 1 карточку","Discard 1 card")</button></div>}
                        else{<button class="training-discard-request" disabled="@(!CanDiscardTraining)" onclick=@RequestTrainingDiscard>@StoreText("Списать выбранную…","Discard selected…")</button>}
                        </div>
                    }
                </div>
            </div>
            <div class="academy-roster"><div class="bench-heading"><label class="section-title">@(GamePreferences.Russian?"Ваши игроки":"Your players")</label><label class="muted localized-text">@StoreText("Выберите игрока для улучшения","Choose a player to upgrade")</label></div><div class="bench-strip">@foreach(var player in C.Cards.Where(p=>!p.IsAcademyLoan).OrderByDescending(p=>p.Overall)){<PlayerCardView Card="@(TrainingAnimation==1 && player.Id==TrainedPlayer?BeforeUpgradePlayer:player)" ClubSeed="@C.ClubSeed" CssClass="@($"bench-player {(Selected.Id==player.Id?"card-selected":"")} training-player-{player.Id}")" OnSelected="@(()=>ChooseUpgradePlayer(player))" />}</div></div>
        </div>
        }
    }
    else if(Game.ClubPage=="Equipment")
    {
        <div class="squad-page equipment-page">
            <div class="equipment-intro"><div><label class="section-title">@(GamePreferences.Russian?"Форма и мячи":"Kits & balls")</label><label class="muted">@(GamePreferences.Russian?"Ваша коллекция. Новые предметы выпадают из паков.":"Your collection. Find new equipment in packs.")</label>@if(C.Pending!=null || C.CupWindow){<label class="muted">@(GamePreferences.Russian?"Смена формы доступна после матча или кубка.":"Equipment changes resume after the match or cup.")</label>}</div><button class="primary save-equipment" disabled="@(C.Pending!=null || C.CupWindow || !C.OwnedKitIds.Contains(PreviewKitId) || !C.OwnedBallIds.Contains(PreviewBallId))" onclick=@(()=>Game.SaveCosmetics(PreviewKitId,PreviewBallId))>@(GamePreferences.Russian?"Сохранить форму":"Save match look")</button></div>
            <div class="equipment-layout">
                <div class="equipment-stage"><ClubCosmeticPreview Card="@EquipmentCard" PlayerSlot="@Array.IndexOf(C.Lineup,EquipmentCard.Id)" KitId="@PreviewKitId" BallId="@PreviewBallId" /><div class="equipment-stage-caption"><label>@EquipmentCard.Name</label><label>@($"{ClubCosmetics.Kit(PreviewKitId).Name} / {ClubCosmetics.Ball(PreviewBallId).Name}")</label></div></div>
                <div class="equipment-collection">
                    <div class="equipment-group"><div class="equipment-group-head"><label>@(GamePreferences.Russian?"Форма":"Football kits")</label><label>@C.OwnedKitIds.Count</label></div><div class="equipment-items">
                    @foreach(var kit in ClubCosmetics.Kits.Where(k=>C.OwnedKitIds.Contains(k.Id))){var design=kit;<div class="equipment-card-entry"><ClubItemCardView Reward="@(EquipmentReward("kit",kit.Id,kit.Name))" CssClass="@($"equipment-card kit-choice-{kit.Id} {(PreviewKitId==kit.Id?"item-selected":"")}")" OnSelected="@(()=>{PreviewKitId=design.Id;})" /><label>@kit.Name</label><label class="equipment-card-status">@(C.EquippedKitId==kit.Id?(GamePreferences.Russian?"Надета":"Equipped"):PreviewKitId==kit.Id?(GamePreferences.Russian?"Просмотр":"Preview"):"")</label></div>}
                    </div></div>
                    <div class="equipment-group"><div class="equipment-group-head"><label>@(GamePreferences.Russian?"Мячи":"Match balls")</label><label>@C.OwnedBallIds.Count</label></div><div class="equipment-items">
                    @foreach(var ball in ClubCosmetics.Balls.Where(b=>C.OwnedBallIds.Contains(b.Id))){var design=ball;<div class="equipment-card-entry"><ClubItemCardView Reward="@(EquipmentReward("ball",ball.Id,ball.Name))" CssClass="@($"equipment-card ball-choice-{ball.Id} {(PreviewBallId==ball.Id?"item-selected":"")}")" OnSelected="@(()=>{PreviewBallId=design.Id;})" /><label>@ball.Name</label><label class="equipment-card-status">@(C.EquippedBallId==ball.Id?(GamePreferences.Russian?"Используется":"Equipped"):PreviewBallId==ball.Id?(GamePreferences.Russian?"Просмотр":"Preview"):"")</label></div>}
                    </div></div>
                </div>
            </div>
        </div>
    }
    else if(Game.ClubPage=="Состав")
    {
        <div class="squad-page">
            <div class="squad-main">
                <div class="squad-field-column">
                    <div class="squad-toolbar"><div><label class="section-title">STARTING ELEVEN</label><label class="muted">@($"{C.FilledSlots}/11 · rating {TeamRating} / 99")</label></div>
                        <div class="formation-buttons">@for(int j=0;j<Formation.All.Length;j++){var index=j;<button class="squad-formation-option @(C.FormationIndex==j?"chosen":"")" disabled="@(!Game.CanEditStartingLineup)" onclick=@(()=>Game.SetFormation(index))>@Formation.All[j].Name</button>}</div>
                    </div>
                    @if(!C.HasCompleteLineup)
                    {
                        <div class="academy-lineup-assist localized-text"><button class="primary complete-academy-lineup" disabled="@(!Game.CanCallAcademy)" onclick=@(()=>Game.CompleteLineupFromAcademy())>@StoreText("Укомплектовать состав","Complete lineup")</button><label>@StoreText("Академия бесплатно даст слабых временных игроков, если своих не хватает.","The academy provides weak temporary players for free if you do not have enough of your own.")</label></div>
                    }
                    <div class="squad-pitch" @ref="SquadPitch">
                        <div class="field-boundary"></div><div class="field-half"></div><div class="field-circle"></div><div class="field-box top"></div><div class="field-box bottom"></div>
                        <label class="pitch-watermark">@C.Shape.Name</label>
                        <SquadSkillLinks Career="@C" Layout="@SquadLayouts[Math.Clamp(C.FormationIndex,0,3)]" Interacting="@(DragCardId>=0 || DetailOpen || Game.GameSettingsOpen || Game.TutorialStep>=0)" />
                        @for(int j=0;j<11;j++)
                        {
                            var slot=j;var player=C.Card(slot);
                            <div class="squad-position squad-position-@slot" style="@SquadSlotStyle(slot)">
                            @if(player!=null){<PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="@($"on-pitch {(DropSlot==slot?"drop-target":"")} squad-slot-{slot}")" OnSelected="@(()=>SelectSlot(slot))" Draggable="@Game.CanEditStartingLineup" OnDragStarted="@(()=>BeginSquadDrag(player.Id))" OnDragMoved="@MoveSquadDrag" OnDragEnded="@EndSquadDrag" />}
                            else{<div class="empty-position @(DropSlot==slot?"drop-target":"")"><img src="/ui-icons/plus.svg" /><b>@PlayerPositions.Slot(C.Shape,slot)</b><label>EMPTY</label></div>}
                            </div>
                        }
                    </div>
                    <div class="squad-skill-legend localized-text"><img src="/ui-icons/attribute-line-v2-passing.svg" /><label>@StoreText("Связки скиллов","Skill combinations")</label><span>@StoreText("Наведите на значок линии, чтобы узнать эффект","Hover a link icon to see its effect")</span></div>
                    <label class="squad-hint">@(!Game.CanEditStartingLineup?"The match has started. Use in-match substitutions to change players.":!string.IsNullOrEmpty(DragMessage) && Time.Now<DragMessageUntil?DragMessage:DragCardId>=0?"Drop the card on a position to swap players.":!C.HasCompleteLineup?"Fill all 11 positions before starting a match.":"Drag to change the lineup · click a card to inspect every attribute")</label>
                </div>
                <div class="bench-section @(DragCardId>=0?"accepts-drop":"")" @ref="BenchArea">
                <div class="bench-heading"><label class="section-title">BENCH</label><label class="muted localized-text">@BenchSummary</label></div>
                <div class="bench-filters"><TextEntry Value:bind="@BenchSearch" Placeholder="Search reserves" /><div>@foreach(var option in new[]{"All","GK","DEF","MID","ATT","DUP"}){var filter=option;<button class="@(BenchFilter==filter?"chosen":"")" onclick=@(()=>BenchFilter=filter)>@(filter=="DUP"?StoreText("Дубли","Duplicates"):filter)</button>}</div><label>@($"{FilteredBench.Length} shown")</label></div>
                <div class="bench-strip" @ref="BenchStrip">
                    @foreach(var player in FilteredBench)
                    {
                        <PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="@($"bench-player reserve-player-{player.Id}")" OnSelected="@(()=>SelectReserve(player.Id))" Draggable="@Game.CanEditStartingLineup" OnDragStarted="@(()=>BeginSquadDrag(player.Id))" OnDragMoved="@MoveSquadDrag" OnDragEnded="@EndSquadDrag" />
                    }
                    @if(FilteredBench.Length==0){<label class="bench-empty">No reserves match these filters.</label>}

                </div>
                </div>
            </div>
        </div>
    }
    else if(Game.ClubPage=="Лига")
    {
        var nextLeague=C.Next(false);var lastLeague=C.League.Where(f=>f.Played && (f.Home==0 || f.Away==0)).OrderByDescending(f=>f.Round).FirstOrDefault();
        <div class="league-screen [email protected]">
            <div class="league-hero">
                <div class="league-emblem large"><label>@LeagueMark(C.Division)</label><span></span></div>
                <div class="league-hero-copy"><label class="eyeline">@($"SEASON {C.Season} · DIVISION {C.Division} OF 5")</label><label class="league-title">@LeagueName(C.Division)</label><label class="league-goal localized-text">@(C.Division==5?StoreText("Итоговое 1-е или 2-е место открывает Кубок чемпионов.","A final top-two finish unlocks the Champions Cup."):StoreText("Первое или второе место даёт повышение. Последнее место — вылет.","Finish in the top two for promotion. Last place is relegated."))</label><div class="league-record"><label>@($"#{Place} IN TABLE")</label><label>@($"{C.Standings().First(r=>r.Team==0).Points} PTS")</label><label>@($"{C.PlayedLeagueRounds}/{C.LeagueRoundCount} PLAYED")</label></div></div>
                <div class="league-play-card">
                    @if(Game.QuickMatchRunning){<label class="eyeline">LIVE SIMULATION</label><label class="league-play-title">@($"{Game.Match.Minute}' · {C.TeamName(0)} {Game.Match.Goals[0]}:{Game.Match.Goals[1]} {Game.Match.AwayName}")</label><div class="league-progress"><div style="@($"width: {Math.Clamp(Game.Match.Minute*100f/90,0,100):0}%;")"></div></div>}
                    else if(C.Pending?.Cup==false){<label class="eyeline">MATCH IN PROGRESS</label><label class="league-play-title">@($"Round {C.ActiveFixture.Round} · {C.TeamName(0)} vs {C.TeamName(Opponent(C.ActiveFixture))}")</label><div class="league-hero-actions"><button class="primary" onclick=@(()=>Game.ResumeMatch())>Watch match →</button><button onclick=@(()=>Game.FinishCurrentLeagueQuickly())>Simulate remaining ↗</button></div>}
                    else if(C.Pending!=null){<label class="eyeline">CUP MATCH IN PROGRESS</label><label class="league-play-title">@(C.ActiveCup?.Name??"Cup") · finish the bracket before league play resumes.</label><button class="primary" onclick=@(()=>Game.ResumeMatch())>Resume cup match →</button>}
                    else if(C.DueCup!=null){<label class="eyeline">CUP WINDOW</label><label class="league-play-title">@($"{C.DueCup.Name} · {CupRoundName(C.DueCup.CurrentRound)}")</label><label class="muted localized-text">@(C.DueCup.Id==ClubCareer.FinalCupId?StoreText("Победа в этом кубке завершит путь к чемпионству.","Win this cup to complete your journey."):"League fixtures resume after the final or elimination.")</label><div class="league-hero-actions"><button class="primary cup-play-match" onclick=@(()=>Game.PrepareCareer(true))>Play cup match →</button><button onclick=@(()=>OpenCup(C.DueCup))>View bracket</button></div>}
                    else if(nextLeague!=null){<label class="eyeline">NEXT MATCHDAY</label><label class="league-play-title">@($"Round {nextLeague.Round} · {C.TeamName(0)} vs {C.TeamName(Opponent(nextLeague))}")</label><div class="league-hero-actions"><button class="primary league-play-match" onclick=@(()=>Game.PrepareCareer(false))>Play match →</button></div>}
                    else{<label class="eyeline">SEASON COMPLETE</label><label class="league-play-title localized-text">@SeasonFinishText</label><div class="league-hero-actions"><button class="primary" disabled="@(!C.SeasonComplete)" onclick=@(()=>Game.NewSeason())>Start next season →</button></div>}
                </div>
            </div>
            <div class="league-content">
                <div class="league-panel league-table-panel"><div class="league-panel-heading"><div><label class="eyeline">THE RACE</label><label class="section-title">Standings</label></div><label class="muted">3 points for a win · 1 for a draw</label></div>
                    <div class="standing heading"><label class="team-cell">CLUB</label><label>P</label><label>W</label><label>D</label><label>L</label><label>GD</label><label>PTS</label></div>
                    @foreach(var row in C.Standings()){<div class="standing @(row.Team==0?"our-team":"")"><button class="team-cell team-link" onclick=@(()=>ShowOpponent(row.Team))><img class="table-crest" src="@C.TeamCrest(row.Team)" /><label>@C.TeamName(row.Team)</label></button><label>@row.Played</label><label>@row.Wins</label><label>@row.Draws</label><label>@row.Losses</label><label>@(row.For-row.Against)</label><label class="points">@row.Points</label></div>}
                    <div class="league-prizes"><label>WIN <b>300 ◈</b></label><label>DRAW <b>75 ◈</b></label><label>LOSS <b>0 ◈</b></label></div>
                    <div class="league-title-prize localized-text"><img class="cup-token-icon" src="/store-packs/cup-token.svg" /><div><label>@StoreText($"1-е место · +{CupEconomy.LeagueTitleReward(C.Division)} кубков",$"1st place · +{CupEconomy.LeagueTitleReward(C.Division)} cup tokens")</label><label>@StoreText("Валюта для кубковых паков · награда после последнего тура","Currency for cup packs · awarded after the final round")</label></div></div>
                </div>
                <div class="league-panel league-fixture-panel"><div class="league-panel-heading"><div><label class="eyeline">YOUR CAMPAIGN</label><label class="section-title">Fixtures &amp; results</label></div><label class="muted">@C.LeagueRoundCount rounds</label></div>
                    @if(lastLeague!=null){<div class="league-recent"><label class="eyeline">@($"LATEST RESULT · ROUND {lastLeague.Round}")</label><img class="fixture-crest" src="@C.TeamCrest(Opponent(lastLeague))" /><label>@($"{C.TeamName(lastLeague.Home)} {lastLeague.HomeGoals} : {lastLeague.AwayGoals} {C.TeamName(lastLeague.Away)}")</label><label class="muted">@(lastLeague.Winner==0?"WIN":lastLeague.Winner<0?"DRAW":"LOSS")</label></div>}
                    <div class="league-fixture-list">@foreach(var f in C.League.Where(f=>f.Home==0 || f.Away==0)){int opponent=Opponent(f);bool current=C.Pending?.Cup==false && C.ActiveFixture==f;<button class="league-fixture-row @(current?"current":"") @(f.Played?"played":"upcoming")" onclick=@(()=>{if(f.Played)ShowMatchReport(f);else ShowOpponent(opponent);})><label class="league-round">@($"R{f.Round:00}")</label><img class="fixture-crest" src="@C.TeamCrest(opponent)" /><label class="league-fixture-opponent">@($"{(f.Home==0?"vs":"at")} {C.TeamName(opponent)}")</label><label class="league-score">@(f.Played?$"{(f.Home==0?f.HomeGoals:f.AwayGoals)} : {(f.Home==0?f.AwayGoals:f.HomeGoals)}":f==nextLeague?"NEXT":"—")</label></button>}</div>
                </div>
            </div>
        </div>
    }
    else if(Game.ClubPage=="PortraitSheet")
    {
        <div class="portrait-sheet"><div class="art-review-heading"><label class="section-title">@(GamePreferences.Russian?"Портреты игроков":"Player portraits")</label><button onclick=@(()=>Game.ClubPage="Главная")>@(GamePreferences.Russian?"Вернуться в клуб":"Return to club")</button></div><div class="portrait-sheet-grid">
        @foreach(var portraitId in PortraitSheetIds){var player=PlayerCatalog.FindVariant(portraitId);if(player==null)continue;<div class="portrait-sheet-entry"><PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="portrait-sheet-card" /><label>@player.Name</label></div>}
        </div></div>
    }
    else if(Game.ClubPage is "CardMaterialReview" or "CardTrainingReview")
    {
        <div class="material-card-review">
            <div class="art-review-heading"><label class="section-title">@(GamePreferences.Russian?"Бронза · Серебро · Золото":"Bronze · Silver · Gold")</label><button onclick=@(()=>Game.ClubPage="Главная")>@(GamePreferences.Russian?"Вернуться в клуб":"Back to club")</button></div>
            <div class="material-review-columns">
            @foreach(var tier in new[]{"BRONZE","SILVER","GOLD","ELITE"})
            {
                var player=PlayerCatalog.Clone(PlayerCatalog.All.Where(p=>p.Rarity==tier && p.Position!="ВР").OrderByDescending(p=>PlayerAppearance.HasArtwork(p.CatalogId)).First());
                <div class="material-review-column"><label class="material-review-title">@tier</label><PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="material-review-large" /><div class="material-review-examples"><PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="bench-player" /><PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="catalog-tile" /></div></div>
            }
            </div>
        </div>
    }
    else if(Game.ClubPage=="CardMaterialItemsReview")
    {
        <div class="material-card-review">
            <div class="art-review-heading"><label class="section-title">@(GamePreferences.Russian?"Материалы карточек предметов":"Item card materials")</label><button onclick=@(()=>Game.ClubPage="Главная")>@(GamePreferences.Russian?"Вернуться в клуб":"Back to club")</button></div>
            <div class="material-review-columns">
                <div class="material-review-column"><label class="material-review-title">BRONZE</label><ClubItemCardView Reward="@(new PackReward{Kind="coins",Name="Club coins",Coins=120})" CssClass="material-review-large" /></div>
                <div class="material-review-column"><label class="material-review-title">SILVER</label><ClubItemCardView Training="@(new TrainingCardItem{Grade=2})" CssClass="material-review-large" /></div>
                <div class="material-review-column"><label class="material-review-title">GOLD</label><ClubItemCardView Reward="@(EquipmentReward("kit","midnight","Midnight Eleven"))" CssClass="material-review-large" /></div>
            </div>
        </div>
    }
    else if(Game.ClubPage=="LegendaryCardReview")
    {
        <div class="legendary-card-review">
            <div class="art-review-heading"><label class="section-title">@(GamePreferences.Russian?"Легендарные карточки":"Legendary cards")</label><button onclick=@(()=>Game.ClubPage="Catalog")>@(GamePreferences.Russian?"Картотека":"Catalog")</button></div>
            <div class="edition-review-columns">
            @foreach(var player in PlayerCatalog.LegendaryCards.OrderBy(p=>p.CatalogId is "PRO-23" or "PRO-54" or "PRO-55" or "PRO-56" or "PRO-57"?0:1))
            {
                <div class="edition-review-column">
                    <label class="edition-review-name">@player.Name</label>
                    <PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="legendary-review-large" />
                    <LegendaryAbilityView Card="@player" Compact="@(true)" />
                    <button class="view-legendary-uniform [email protected]()" onclick=@(()=>{ReviewLegendId=player.CatalogId;ReviewAngle=1;Game.ClubPage="LegendaryUniformReview";})>@(GamePreferences.Russian?"Образ и фирменный приём":"Appearance and signature")</button>
                </div>
            }
            </div>
        </div>
    }
    else if(Game.ClubPage=="LegendaryUniformReview")
    {
        <div class="player-art-review legendary-uniform-review">
            <div class="art-review-heading"><div><label class="eyeline">@(GamePreferences.Russian?"ОБРАЗ НА ПОЛЕ":"MATCH APPEARANCE")</label><label class="section-title">@ReviewLegend.Name</label></div><button class="legendary-review-back" onclick=@(()=>Game.ClubPage="LegendaryCardReview")>@(GamePreferences.Russian?"К карточкам":"Back to cards")</button></div>
            <div class="art-comparison-toolbar"><div class="art-review-angles">@foreach(int angle in new[]{1,3,2,4}){int view=angle;<button class="art-review-angle art-review-angle-@view @(ReviewAngle==view?"selected":"")" onclick=@(()=>ReviewAngle=view)>@(GamePreferences.Russian?new[]{"Профиль","Анфас","Со спины","Три четверти","В полный рост"}[view]:new[]{"Profile","Front","Back","Three quarters","Full body"}[view])</button>}</div></div>
            <div class="legendary-outfit-body"><div class="art-comparison-grid">@foreach(var pilot in ReviewLegendVersions){<div class="art-comparison-player"><label class="art-comparison-name">@(pilot.Edition==CardRatings.Legendary?(GamePreferences.Russian?"Легендарная версия":"Legendary edition"):(GamePreferences.Russian?"Обычная версия":"Standard edition"))</label><div class="art-comparison-content"><div class="art-comparison-card"><PlayerCardView Card="@pilot" ClubSeed="@C.ClubSeed" CssClass="art-review-card" /></div><ClubCosmeticPreview Card="@pilot" PlayerSlot="@(pilot.Position=="ВР"?0:9)" KitId="@C.EquippedKitId" BallId="@C.EquippedBallId" FixedFacing="@(ReviewAngle==1?1.0f:ReviewAngle==2?4.65f:ReviewAngle==3?1.78f:1.0f)" Closeup="@(ReviewAngle!=4)" /></div></div>}</div><LegendaryAbilityView Card="@ReviewLegend" /></div>
        </div>
    }
    else if(Game.ClubPage=="CartoonPortraitReview")
    {
        <div class="cartoon-portrait-review">
            <div class="art-review-heading"><label class="section-title">@(GamePreferences.Russian?"Тест мультяшных портретов":"Cartoon portrait test")</label><button onclick=@(()=>Game.ClubPage="Главная")>@(GamePreferences.Russian?"Вернуться в клуб":"Back to club")</button></div>
            <div class="cartoon-portrait-pairs">
            @foreach(var identity in new[]{PlayerAppearance.HaalandId,PlayerAppearance.MessiId})
            {
                var player=PlayerCatalog.Find(identity);
                <div class="cartoon-portrait-pair"><label class="section-title">@player.Name</label><div class="cartoon-portrait-cards">
                    <div><PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="cartoon-test-card" /><label>@(GamePreferences.Russian?"Текущий":"Current")</label></div>
                    <div><PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="cartoon-test-card" PortraitOverride="@(identity==PlayerAppearance.HaalandId?"/portraits/haaland-cartoon-test-v1.png":"/portraits/messi-cartoon-test-v1.png")" /><label>@(GamePreferences.Russian?"Мультяшный тест":"Cartoon test")</label></div>
                </div></div>
            }
            </div>
            <label class="cartoon-portrait-status">@(GamePreferences.Russian?"Тестовые портреты Холанда и Месси для выбора стиля карточек.":"Haaland and Messi test portraits for reviewing the card art style.")</label>
        </div>
    }
    else if(Game.ClubPage=="PortraitReview")
    {
        <div class="player-art-review">
            <div class="art-review-heading"><div><label class="eyeline">@(GamePreferences.Russian?"СРАВНЕНИЕ ПОРТРЕТОВ И МОДЕЛЕЙ":"PORTRAIT & MODEL COMPARISON")</label><label class="section-title">@(GamePreferences.Russian?"Обзор игроков":"Player review")</label></div><button onclick=@(()=>Game.ClubPage="Главная")>@(GamePreferences.Russian?"Вернуться в клуб":"Back to club")</button></div>
            <div class="art-comparison-toolbar"><div class="art-review-angles">@foreach(int angle in new[]{4,3,0,1,2}){int view=angle;<button class="art-review-angle art-review-angle-@view @(ReviewAngle==view?"selected":"")" onclick=@(()=>ReviewAngle=view)>@(GamePreferences.Russian?new[]{"Профиль","Три четверти","Со спины","Анфас","В полный рост"}[view]:new[]{"Profile","Three quarters","Back","Front","Full body"}[view])</button>}</div><button class="art-review-clay" onclick=@(()=>ReviewClay=!ReviewClay)>@(GamePreferences.Russian?(ReviewClay?"Показать в цвете":"Проверить скульптуру"):(ReviewClay?"Show colours":"Inspect sculpt"))</button></div>
            <div class="art-comparison-grid">
            @foreach(var id in PortraitReviewIds)
            {
                var pilot=PlayerCatalog.Find(id);int shirt=id==PlayerAppearance.HaalandId?8:9;
                <div class="art-comparison-player"><label class="art-comparison-name">@pilot.Name</label><div class="art-comparison-content"><div class="art-comparison-card"><PlayerCardView Card="@pilot" ClubSeed="@C.ClubSeed" CssClass="art-review-card" /><label class="muted">@(GamePreferences.Russian?"Иллюстрация для карточки":"Illustrated card portrait")</label></div><ClubCosmeticPreview Card="@pilot" PlayerSlot="@shirt" KitId="@C.EquippedKitId" BallId="@C.EquippedBallId" FixedFacing="@(ReviewFacingOverride??(ReviewAngle==0?2.57f:ReviewAngle==1?1.78f:ReviewAngle==2?4.65f:1.0f))" Closeup="@(ReviewCloseupOverride || (ReviewAngle!=2 && ReviewAngle!=4))" Clay="@ReviewClay" ForceLowDetail="@ReviewLowDetail" /></div></div>
            }
            </div>
        </div>
    }
    else if(Game.ClubPage=="CrestReview")
    {
        <div class="crest-review-grid">@foreach(var club in ClubCatalog.All.Where(c=>c.Division==CrestReviewDivision)){<div><img src="@club.Crest" /><label>@club.Name</label></div>}</div>
    }
    else if(Game.ClubPage=="Missions")
    {
        int points=C.Standings().First(r=>r.Team==0).Points;
        <div class="missions-page">
            <div class="missions-heading"><div><label class="eyeline">@($"SEASON {C.Season}")</label><label class="section-title">Season missions</label></div><label>@(StoreText($"Наград доступно: {C.ClaimableMissions+C.ClaimableCareerRewards}",$"{C.ClaimableMissions+C.ClaimableCareerRewards} rewards ready"))</label></div>
            <div class="mission-grid">
            @foreach(var mission in C.Checkpoints)
            {
                var round=mission.Round;
                <div class="mission-tile @(mission.Claimed?"claimed":mission.Earned?"ready":mission.Resolved?"missed":"")">
                    <img class="mission-icon" src="/ui-icons/ui-bold-nav-missions.svg" /><label class="mission-name">@mission.Label</label>
                    <label class="mission-task">@($"Earn {mission.RequiredPoints} points by round {mission.Round}")</label>
                    <div class="mission-progress"><div style="@($"width:{Math.Min(100,points*100/mission.RequiredPoints)}%;")"></div></div>
                    <div class="mission-status"><label>@($"{Math.Min(points,mission.RequiredPoints)}/{mission.RequiredPoints} PTS")</label><b>@($"+{mission.CoinPrize} ◈")</b></div>
                    <button class="primary claim-mission-@round" disabled="@(!mission.Earned || mission.Claimed)" onclick=@(()=>ClaimMission(round))>@(mission.Claimed?"CLAIMED":mission.Earned?"CLAIM REWARD":mission.Resolved?"MISSED":"IN PROGRESS")</button>
                </div>
            }
            </div>
            <CareerAchievementsView Career="@C" OnClaim="@ClaimCareerReward" />
            <PlatformAchievementsView Game="@Game" />
            <label class="section-title">Cup milestones</label>
            <div class="mission-grid cup-mission-grid">
            @foreach(var cup in C.Tournaments.OrderBy(t=>t.OpensAfterRound))
            {
                <button class="mission-tile cup-mission" onclick=@(()=>OpenCup(cup))><img class="mission-icon" src="/ui-icons/ui-bold-nav-cup.svg" /><label class="mission-name">@cup.Name</label><label class="mission-task">@($"Complete {cup.OpensAfterRound} league matches to unlock")</label><div class="mission-progress"><div style="@($"width:{Math.Min(100,C.PlayedLeagueRounds*100/cup.OpensAfterRound)}%;")"></div></div><label class="mission-task">@(cup.Won?"TROPHY WON":cup.Eliminated?"ELIMINATED":C.PlayedLeagueRounds>=cup.OpensAfterRound?"CUP AVAILABLE":"LOCKED")</label><label class="mission-cup-prize localized-text">@CupPrizeSummary(cup)</label></button>
            }
            </div>
        </div>
    }
    else if(Game.ClubPage=="Кубок")
    {
        var viewed=ViewedCup;
        <div class="cups-page">
            <CareerFinaleView Career="@C" OnOpenCup="@(()=>OpenCup(C.FinalCup))" />
            <div class="cups-heading"><div><label class="eyeline">SOCER / KNOCKOUT FOOTBALL</label><label class="section-title">Cup competitions</label><label class="muted">Cups unlock during the league season. Play one tournament at a time.</label></div><div class="cups-season">@($"SEASON {C.Season}")</div></div>
            @if(viewed==null)
            {
                <div class="cup-tiles">
                    @foreach(var cup in C.Tournaments.OrderBy(t=>t.OpensAfterRound))
                    {
                        var choice=cup;bool available=CanInspectCup(cup);int played=cup.Games.Count(f=>f.Played && (f.Home==0 || f.Away==0));
                        <button class="cup-tile [email protected] [email protected] @(available?"available":"locked")" disabled="@(!available)" onclick=@(()=>OpenCup(choice))>
                            <div class="cup-tile-top"><label class="cup-tile-status">@CupStatus(cup)</label><label class="cup-tile-format">8 CLUBS / 3 ROUNDS</label></div>
                            <div class="cup-tile-art"><span class="cup-tile-emblem">@cup.Mark</span>@if(!available && !cup.Finished){<img class="cup-tile-lock" src="/ui-icons/ui-bold-nav-lock.svg" />}</div>
                            <label class="cup-tile-name localized-text">@(cup.Id=="final"?StoreText("Кубок чемпионов","Champions Cup"):cup.Name)</label>
                            <div class="cup-tile-prizes"><div><label>ROUND WIN</label><label class="cup-prize-value">@($"+{cup.RoundPrize} ◈")</label><div class="cup-token-reward localized-text"><img class="cup-token-icon" src="/store-packs/cup-token.svg" /><label>@($"+{CupEconomy.MatchWinReward(C.Division)}")</label></div></div><div><label>TROPHY BONUS</label><label class="cup-prize-value">@($"+{cup.TrophyPrize} ◈")</label></div></div>
                            <div class="cup-tile-entry">
                                <div class="cup-tile-rounds"><label>YOUR CUP RUN</label><label class="cup-round-count">@($"{played}/3")</label></div><label class="cup-tile-cta">@(available?(cup.Finished || cup.Eliminated?StoreText("Смотреть сетку →","View bracket →"):cup.Started?"Continue cup →":"Open tournament →"):CupRequirement(cup))</label>
                            </div>
                        </button>
                    }
                </div>
                @if(!C.Tournaments.Any(CanViewCup))
                {
                    <div class="cups-empty"><label>@(GamePreferences.Russian?"Сейчас нет доступных кубков":"No cups are available right now")</label><label>@(C.Tournaments.Any(t=>!t.Finished && !t.Eliminated)?GamePreferences.Russian?"Продолжайте сезон лиги — кубки появятся после открытия и завершения текущего матча.":"Continue the league season. Cups appear when they open and the current match is finished.":GamePreferences.Russian?"Итоги участия в завершённых кубках сохранены в истории ниже.":"Your completed cup runs are saved in the history below.")</label></div>
                }
                <div class="cup-library-note"><label>ONE CUP AT A TIME</label><span>League matches resume after the final or elimination. Packs, transfers and training are locked during a cup run.</span></div>
            }
            @if(viewed!=null)
            {
                <button class="cup-library-back" onclick=@(()=>ViewedCupId="")>← All cups</button>
                <div class="cup-stage [email protected]">
                    <div class="cup-stage-header"><div class="cup-stage-crest"><span>@viewed.Mark</span></div><div><label class="eyeline">@($"SEASON {C.Season} · EIGHT CLUB KNOCKOUT")</label><label class="cup-stage-name">@viewed.Name</label><label class="muted localized-text">@CupPrizeSummary(viewed)</label></div><div class="cup-stage-action">@if(C.Pending?.Cup==true && C.MatchCup?.Id==viewed.Id){<button class="primary" onclick=@(()=>Game.ResumeMatch())>Resume match →</button>}else if(C.Pending==null && C.DueCup?.Id==viewed.Id && viewed.NextNorth!=null){<button class="primary cup-play-match" onclick=@(()=>Game.PrepareCareer(true))>@($"Play {CupRoundName(viewed.CurrentRound)} →")</button>}else{<label>@(viewed.Won?"TROPHY WON":viewed.Eliminated?"CAMPAIGN ENDED":C.DueCup==null?"NOT YET OPEN":"ANOTHER CUP IS ACTIVE")</label>}</div></div>
                    <div class="cup-story"><div><label>01</label><span>QUARTERFINALS</span></div><div><label>02</label><span>SEMIFINALS</span></div><div><label>03</label><span>FINAL</span></div></div>
                    @if(viewed.ChampionClubId>=0){<div class="cup-world-champion localized-text"><label>@StoreText("Обладатель кубка","Cup champion")</label><b>@C.TeamName(viewed.Final.Winner,viewed)</b></div>}
                    <div class="cup-bracket">
                        @for(int j=1;j<=3;j++)
                        {
                            int round=j;
                            <div class="cup-round"><label class="eyeline">@CupRoundName(round)</label>
                                @foreach(var fixture in viewed.Games.Where(f=>f.Round==round))
                                {<div class="cup-game @(fixture.Home==0 || fixture.Away==0?"north-game":"") @(fixture.Played?"completed":"")"><div class="cup-game-club @(fixture.Played && fixture.Winner==fixture.Home?"winner":"")"><img class="club-initial" src="@C.TeamCrest(fixture.Home,viewed)" /><label>@C.TeamName(fixture.Home,viewed)</label><b>@(fixture.Played?fixture.HomeGoals.ToString():"—")</b></div><div class="cup-game-club @(fixture.Played && fixture.Winner==fixture.Away?"winner":"")"><img class="club-initial" src="@C.TeamCrest(fixture.Away,viewed)" /><label>@C.TeamName(fixture.Away,viewed)</label><b>@(fixture.Played?fixture.AwayGoals.ToString():"—")</b></div>@if(fixture.Penalties){<label class="cup-penalties">@($"PEN {fixture.HomePenalties}:{fixture.AwayPenalties} · {C.TeamName(fixture.Winner,viewed)} through")</label>}</div>}
                                @if(!viewed.Games.Any(f=>f.Round==round)){<div class="cup-game placeholder">Winners advance here</div>}
                            </div>
                        }
                    </div>
                    <div class="cup-stage-footer">@if(viewed.Id==ClubCareer.FinalCupId){<label class="localized-text">@(viewed.Won?StoreText("Вы победили в игре. Можно продолжить карьеру с этим составом.","You won the game. You can continue your career with this squad."):viewed.Eliminated?StoreText("Попробуйте снова: итоговый топ-2 Премьер-лиги в новом сезоне откроет кубок заново.","Try again: a top-two Premier League finish next season unlocks another attempt."):StoreText("Последний шаг: выиграйте три раунда и станьте обладателем главного трофея.","The last step: win three rounds to lift the final trophy."))</label>}else if(viewed.Finished || viewed.Eliminated){<label class="localized-text">@StoreText("Ваше участие завершено. Можно продолжить сезон лиги.","Your cup run is over. You can continue the league season.")</label>}else{<label>ELIMINATION ENDS THE WINDOW</label><label>LEAGUE MATCHES RESUME AFTER YOUR CUP RUN</label><label>OWNED PLAYERS CAN BE REARRANGED · STORE LOCKED</label>}</div>
                </div>
            }
            <div class="cup-history-panel">
                <div class="cup-history-heading"><label class="section-title">@(GamePreferences.Russian?"Результаты кубков":"Cup results")</label></div>
                <div class="cup-history-columns"><label>@(GamePreferences.Russian?"СЕЗОН":"SEASON")</label><label>@(GamePreferences.Russian?"КУБОК":"CUP")</label><label>@(GamePreferences.Russian?"МЕСТО":"PLACE")</label></div>
                @foreach(var result in C.CupResults){<div class="cup-history-table-row @(result.PlaceFrom==1?"champion":"")"><label>@result.Season</label><div class="cup-history-cup"><label>@result.CupName</label>@if(result.ChampionClubId>=0){<label class="cup-history-world-champion localized-text">@($"{StoreText("Обладатель кубка","Cup champion")}: {result.ChampionName}")</label>}</div><label class="cup-history-place">@CupPlace(result)</label></div>}
                @if(!C.CupResults.Any()){<label class="cup-history-empty">@(GamePreferences.Russian?"Здесь появятся итоги завершённых кубков.":"Completed cup runs will appear here.")</label>}
                <label class="cup-history-note">@(GamePreferences.Russian?"Без матча за места полуфиналисты делят 3–4-е место, четвертьфиналисты — 5–8-е.":"Without placement playoffs, semifinalists share 3rd–4th place and quarterfinalists share 5th–8th.")</label>
            </div>
        </div>
    }
    else if(Game.ClubPage=="Catalog")
    {
        <div class="catalog-page">
            <div class="catalog-section-tabs localized-text">
                <button class="catalog-section-players @(!CatalogSkills?"chosen":"")" onclick=@(()=>SelectCatalogSection(false))><img src="/ui-icons/ui-bold-nav-catalog.svg" /><label>@StoreText("Футболисты","Players")</label></button>
                <button class="catalog-section-skills @(CatalogSkills?"chosen":"")" onclick=@(()=>SelectCatalogSection(true))><img src="/ui-icons/ui-bold-nav-training.svg" /><label>@StoreText("Скиллы","Skills")</label></button>
            </div>
            @if(CatalogSkills)
            {
                <SkillCatalogView />
            }
            else
            {
            var visible=FilteredCatalog.ToList();
            CatalogPage=Math.Clamp(CatalogPage,0,Math.Max(0,(visible.Count-1)/24));
            var inspected=visible.FirstOrDefault(p=>CatalogOwned?p.Id==SelectedCatalogCopyId:p.CardKey==SelectedCatalogKey)??visible.FirstOrDefault();
            <div class="catalog-intro localized-text"><div><label class="section-title">@StoreText("Футболисты","Players")</label><label class="muted">@StoreText($"{(CatalogOwned?"Копий":"Карточек")}: {visible.Count} · в клубе: {C.Cards.Count} · найдено игроков: {C.SeenCatalogIds.Count}",$"{visible.Count} {(CatalogOwned?"copies":"cards")} · {C.Cards.Count} in your club · {C.SeenCatalogIds.Count} discovered")</label></div><label class="muted">@StoreText("У каждой копии свои скиллы. Меняйте их карточками улучшений.","Each copy has its own skills. Change them using upgrade cards.")</label></div>
            <div class="catalog-filters">
                <div class="catalog-search-row"><TextEntry class="catalog-search" Value:bind="@CatalogSearch" Placeholder="Search player or country" /><CatalogCountryPicker Selected="@CatalogCountry" OnSelected="@SelectCatalogCountry" /></div>
                <div class="catalog-filter-row">@foreach(var tier in new[]{"All tiers","Bronze","Silver","Gold","Elite","Legendary"}){var option=tier;<button class="catalog-tier-@(tier=="All tiers"?"all":tier.ToLowerInvariant()) @(CatalogTier==option?"chosen":"")" onclick=@(()=>{CatalogTier=option;CatalogPage=0;})>@option</button>}</div>
                <div class="catalog-filter-row catalog-sort-row"><label>@(GamePreferences.Russian?"Сортировка":"Sort by")</label><button class="catalog-sort-rating @(CatalogSort=="rating"?"chosen":"")" onclick=@(()=>{CatalogSort="rating";CatalogPage=0;})>@(GamePreferences.Russian?"Рейтинг ↓":"Overall ↓")</button><button class="catalog-sort-type @(CatalogSort=="type"?"chosen":"")" onclick=@(()=>{CatalogSort="type";CatalogPage=0;})>@(GamePreferences.Russian?"Тип: бронза → легенда":"Type: Bronze → Legendary")</button></div>
                <div class="catalog-filter-row">@foreach(var role in new[]{"All positions"}.Concat(PlayerPositions.Standard.Where(position=>PlayerCatalog.CardVariants.Any(p=>PlayerPositions.Card(p)==position)))){var option=role;<button class="@(CatalogPosition==option?"chosen":"")" onclick=@(()=>{CatalogPosition=option;CatalogPage=0;})>@option</button>}<button class="catalog-owned-toggle @(CatalogOwned?"chosen":"")" onclick=@(()=>{CatalogOwned=!CatalogOwned;CatalogPage=0;SelectedCatalogCopyId=-1;DetailOpen=false;})>Owned only</button></div>
            </div>
            <div class="catalog-card-actions localized-text"><button class="view-legendary-card" onclick=@(()=>{DetailOpen=false;Game.ClubPage="LegendaryCardReview";})>@StoreText($"Легенды · {PlayerCatalog.LegendaryCards.Count}",$"Legends · {PlayerCatalog.LegendaryCards.Count}")</button></div>
            <div class="catalog-content">
                <div class="catalog-results">
                    <div class="catalog-grid">@foreach(var player in visible.Skip(CatalogPage*24).Take(24))
                    {<div class="catalog-copy-tile"><PlayerCardView Card="@player" ClubSeed="@C.ClubSeed" CssClass="catalog-tile" OnSelected="@(()=>InspectCatalog(player,CatalogOwned))" />@if(CatalogOwned){<label class="catalog-copy-caption localized-text">@CopyCaption(player)</label>}</div>}
                    </div>
                    <div class="catalog-pagination"><button disabled="@(CatalogPage==0)" onclick=@(()=>CatalogPage=Math.Max(0,CatalogPage-1))>← Previous</button><label>@($"Page {CatalogPage+1} / {Math.Max(1,(visible.Count+23)/24)}")</label><button disabled="@((CatalogPage+1)*24>=visible.Count)" onclick=@(()=>CatalogPage++)>Next →</button></div>
                </div>
            </div>
            }
        </div>
    }
    else
    {
        <div class="squad-page scout-screen">
            @if(PackRevealActive && Game.RevealedPack!=null)
            {<div class="pack-cinema-placeholder"></div>}
            else
            {
            <div class="pack-store localized-text @(StoreCupPacks?"cup-pack-store":"")">
                <div class="store-heading"><label class="section-title">@StoreText("Магазин клуба","Club store")</label><div class="store-tabs"><button class="store-tab-buy @(!StoreInventory?"chosen":"")" onclick=@(()=>SetStoreTab(false))>@StoreText("Купить","Buy")</button><button class="store-tab-inventory @(StoreInventory?"chosen":"")" onclick=@(()=>SetStoreTab(true))><label>@StoreText("Инвентарь","Inventory")</label><b>@C.PackInventory.Sum()</b></button></div></div>
                <div class="store-category-row"><div class="store-categories"><button class="store-category-coins @(!StoreCupPacks && !StoreCapsules?"chosen":"")" onclick=@(()=>SetStoreCurrency(false))><span class="nav-icon-ai ai-coins"></span><label>@StoreText("За монеты","Coins")</label>@if(StoreInventory){<b>@StoreOwnedCount(false)</b>}</button><button class="store-category-cups @(StoreCupPacks && !StoreCapsules?"chosen":"")" onclick=@(()=>SetStoreCurrency(true))><img class="cup-token-icon" src="/store-packs/cup-token.svg" /><label>@StoreText("За кубки","Cup tokens")</label>@if(StoreInventory){<b>@StoreOwnedCount(true)</b>}</button><button class="store-category-capsules @(StoreCapsules?"chosen":"")" onclick=@SetStoreCapsules><img class="capsule-category-icon" src="/ui-icons/item-upgrade-metal-v1.svg" /><label>@StoreText("Улучшения","Upgrades")</label>@if(StoreInventory){<b>@CapsuleOwnedCount</b>}</button></div>@if(StoreCupPacks){<label class="store-currency-tip">@StoreText("Кубки — за победы в кубковых матчах и 1-е место в лиге.","Earn cup tokens by winning cup matches or finishing 1st in your league.")</label>}</div>
                @if(C.CupWindow || C.Pending!=null){<div class="store-lock-note"><img class="nav-icon" src="/ui-icons/ui-bold-nav-lock.svg" /><label>@StoreText(C.CupWindow?"Магазин откроется после кубка.":"Завершите текущий матч, чтобы использовать магазин.",C.CupWindow?"The store reopens after your cup run.":"Finish your current match to use the store.")</label></div>}
                @if(StoreInventory && VisibleStoreOwnedCount==0)
                {<div class="store-empty"><img src="@(StoreCupPacks?"/store-packs/cup-token.svg":"/ui-icons/ui-bold-nav-scout.svg")" /><label>@StoreText(StoreCapsules?"Капсул пока нет":StoreCupPacks?"Кубковых паков пока нет":"Пока нет паков",StoreCapsules?"No capsules yet":StoreCupPacks?"No cup packs yet":"No packs yet")</label><label class="muted">@StoreText("Купленные паки будут храниться здесь.","Purchased packs are stored here.")</label><button class="primary inventory-to-buy" onclick=@(()=>SetStoreTab(false))>@StoreText("Выбрать пак","Browse packs")</button></div>}
                else
                {
                <div class="store-pack-grid">
                    @for(int i=0;i<ScoutPacks.All.Length;i++)
                    {
                        int pack=i;var offer=ScoutPacks.All[i];bool locked=C.Division<offer.UnlockDivision;
                        if(offer.UpgradeOnly!=StoreCapsules || (!StoreCapsules && offer.UsesCupTokens!=StoreCupPacks))continue;
                        if(StoreInventory && C.OwnedPacks(pack)==0)continue;
                        <div class="store-pack [email protected]() @(offer.UsesCupTokens?"cup-store-pack":"") @(!StoreInventory && locked?"locked":"")">
                            <div class="store-pack-art store-details-@pack" onclick=@(()=>ShowStoreOffer(pack))><div class="store-pack-aura"></div><img class="store-pack-image" src="@PackArt(pack)" />@if(!StoreInventory && locked){<div class="store-padlock"><img src="/ui-icons/ui-bold-nav-lock.svg" /></div>}</div>
                            <label class="store-pack-name">@(offer.UsesCupTokens?StoreText("Кубковый пак","Cup pack"):PackName(pack))</label>@if(offer.UsesCupTokens){<label class="store-pack-league">@StoreLeagueName(offer.UnlockDivision)</label>}<label class="store-contents">@(offer.UpgradeOnly?StoreText("1 карточка улучшения","1 upgrade card"):StoreText("1–2 футболиста · 1–3 дополнения","1–2 footballers · 1–3 extras"))</label>@if(offer.UsesCupTokens){<label class="store-quality">@(offer.Legendary>0?StoreText("Золото · Элита · Легенды","Gold · Elite · Legendary"):StoreText("Золото · Элита","Gold · Elite"))</label>}
                            @if(offer.UpgradeOnly){<div class="capsule-drop-odds">@for(int grade=1;grade<=3;grade++){<div><label>@TrainingGradeName(grade)</label><b>@($"{offer.Weight(grade-1)}%")</b></div>}</div>}
                            @if(StoreInventory){<label class="store-owned-count">@StoreText($"В наличии: {C.OwnedPacks(pack)}",$"Owned: {C.OwnedPacks(pack)}")</label><button class="primary open-owned-pack open-owned-@pack" title="@PackSpaceHint(pack)" disabled="@(!C.CanOpenOwnedPack(pack))" onclick=@(()=>OpenStorePack(pack))>@(offer.UpgradeOnly?StoreText("Открыть капсулу","Open capsule"):StoreText("Открыть пак","Open pack"))</button>@if(PackSpaceHint(pack)!=""){<label class="inventory-capacity-note">@PackSpaceHint(pack)</label>}}
                            else if(locked){<label class="store-unlock">@StoreText($"Откроется: {StoreLeagueName(offer.UnlockDivision)}",$"Unlocks in {StoreLeagueName(offer.UnlockDivision)}")</label><button class="store-info-@pack" onclick=@(()=>ShowStoreOffer(pack))>@StoreText("Подробнее","Details")</button>}
                            else{<div class="store-price @(offer.UsesCupTokens?"cup-token-price":"")"><label>@($"{offer.Cost:N0}")</label>@if(offer.UsesCupTokens){<img class="cup-token-icon" src="/store-packs/cup-token.svg" />}else{<label>◈</label>}</div><button class="primary buy-packs buy-packs-@pack" onclick=@(()=>ShowStoreOffer(pack))>@StoreText("Выбрать","View pack")</button>}
                        </div>
                    }
                </div>
                }
                @if(Time.Now<StoreFeedbackUntil){<label class="store-feedback">@StoreFeedback</label>}
                @if(StoreOfferIndex>=0)
                {
                    var offer=ScoutPacks.All[StoreOfferIndex];int pack=StoreOfferIndex;
                    <div class="store-modal-backdrop"><div class="store-purchase-modal [email protected]() @(offer.UsesCupTokens?"cup-purchase-modal":"")">
                        <button class="store-modal-close" onclick=@(()=>StoreOfferIndex=-1)>✕</button>
                        <div class="store-modal-art"><img src="@PackArt(pack)" /></div>
                        <div class="store-modal-copy"><label class="store-modal-title">@PackName(pack)</label><label class="store-modal-description">@PackDescription(pack)</label>
                            @if(offer.UpgradeOnly){<div class="store-content-facts"><label>@StoreText("1 карточка улучшения","1 upgrade card")</label></div><div class="capsule-drop-odds">@for(int grade=1;grade<=3;grade++){<div><label>@TrainingGradeName(grade)</label><b>@($"{offer.Weight(grade-1)}%")</b></div>}</div>}
                            else{<div class="store-content-facts"><label>@StoreText("1–2 футболиста","1–2 footballers")</label><label>@StoreText("1–3 дополнения","1–3 extras")</label></div>
                            <label class="muted">@(offer.UsesCupTokens?StoreText("Золотые карточки улучшений, редкая форма и мячи. В каждом паке есть улучшение. Возможны дубли.","Gold upgrade cards, rare kits and balls. Every pack includes an upgrade. Duplicates can drop."):StoreText("Карточки улучшений, форма и мячи. В каждом паке есть улучшение. Возможны дубли.","Upgrade cards, kits and balls. Every pack includes an upgrade. Duplicates can drop."))</label>
                            }
                            @if(offer.UsesCupTokens){<div class="cup-pack-chances"><div><label>@StoreText("Элитный игрок","Elite player")</label><b>@($"{offer.Elite}%")</b></div>@if(offer.Legendary>0){<div class="legendary-drop-chance"><label>@StoreText("Легендарный игрок","Legendary player")</label><b>@($"{offer.Legendary}%")</b></div>}<label>@StoreText("Шанс на каждого выпавшего футболиста.","Chance for each footballer drawn.")</label></div>}
                            @if(StoreInventory){<label class="store-price">@StoreText($"В наличии: {C.OwnedPacks(pack)}",$"Owned: {C.OwnedPacks(pack)}")</label><button class="primary store-modal-open" title="@PackSpaceHint(pack)" disabled="@(!C.CanOpenOwnedPack(pack))" onclick=@(()=>{StoreOfferIndex=-1;OpenStorePack(pack);})>@(offer.UpgradeOnly?StoreText("Открыть капсулу","Open capsule"):StoreText("Открыть пак","Open pack"))</button>@if(PackSpaceHint(pack)!=""){<label class="inventory-capacity-note">@PackSpaceHint(pack)</label>}}
                            else
                            {
                                <div class="store-modal-quantity"><label>@StoreText("Количество","Quantity")</label><div><button class="quantity-minus" disabled="@(BuyQuantity<=1)" onclick=@(()=>BuyQuantity=Math.Max(1,BuyQuantity-1))>−</button><b>@BuyQuantity</b><button class="quantity-plus" disabled="@(BuyQuantity>=10)" onclick=@(()=>BuyQuantity=Math.Min(10,BuyQuantity+1))>+</button>@foreach(var quantity in new[]{1,5,10}){int count=quantity;<button class="store-quantity-@quantity @(BuyQuantity==quantity?"chosen":"")" onclick=@(()=>BuyQuantity=count)>@quantity</button>}</div></div>
                                <div class="store-modal-balance"><label>@StoreText("В наличии","Balance")</label><label>@StoreCurrencyAmount(offer,offer.UsesCupTokens?C.CupTokens:C.Coins)</label></div>
                                <div class="store-modal-total"><label>@StoreText("Итого","Total")</label><div class="store-total-value @(offer.UsesCupTokens?"cup-token-price":"")"><b>@($"{offer.Cost*BuyQuantity:N0}")</b>@if(offer.UsesCupTokens){<img class="cup-token-icon" src="/store-packs/cup-token.svg" />}else{<b>◈</b>}</div></div>
                                @if(!C.CanBuyPacks(pack,BuyQuantity)){<label class="store-block-reason">@StoreBlockReason(pack)</label>}
                                <button class="primary store-confirm-purchase" disabled="@(!C.CanBuyPacks(pack,BuyQuantity))" onclick=@(()=>BuyStorePacks(pack))>@StoreText("Купить в инвентарь","Buy to inventory")</button>
                            }
                        </div>
                    </div></div>
                }
            </div>
            }
        </div>
    }
    </div>

    @if(DragCardId>=0 && DragCard!=null){<div class="squad-drag-ghost" @ref="DragGhost" style="@DragGhostStyle()"><PlayerCardView Card="@DragCard" ClubSeed="@C.ClubSeed" CssClass="drag-preview" /></div>}
    @if(SkillLibraryOpen)
    {
        <div class="skill-library-overlay localized-text"><button class="skill-library-scrim" onclick=@(()=>SkillLibraryOpen=false)></button><div class="skill-library-dialog"><div class="skill-library-heading"><div><label>@StoreText("Скиллы для вашей игровой роли","Skills for this playing role")</label><span>@($"{Selected.Name} · {PlayerPositions.Card(Selected)} · {UniqueSkills.Pool(Selected).Count} "+StoreText("вариантов","skills"))</span></div><button class="skill-library-close" onclick=@(()=>SkillLibraryOpen=false)>✕</button></div><div class="skill-library-grades"><button class="skill-library-normal @(SkillLibraryGrade==1?"chosen":"")" onclick=@(()=>SkillLibraryGrade=1)>@UniqueSkills.GradeName(1,GamePreferences.Russian)</button><button class="skill-library-gold @(SkillLibraryGrade==2?"chosen":"")" onclick=@(()=>SkillLibraryGrade=2)>@UniqueSkills.GradeName(2,GamePreferences.Russian)</button><label>@StoreText("Получение — случайно через карточки улучшений.","Obtained randomly using upgrade cards.")</label></div><div class="skill-library-list">@foreach(var eligible in UniqueSkills.Pool(Selected)){<CardSkillView Instance="@(new SkillInstance{Skill=eligible,Grade=SkillLibraryGrade})" />}</div></div></div>
    }
    @if(DetailOpen && (Game.ClubPage=="Состав" || Game.ClubPage=="Catalog"))
    {
        var profile=Game.ClubPage=="Catalog"?CardCollectionView.Inspect(C,SelectedCatalogKey,SelectedCatalogCopyId):Selected;
        var profileSlot=Game.ClubPage=="Catalog"?-1:DetailSlot;
        if(profile!=null)
        {
        <div class="player-profile-overlay">
            <button class="player-profile-scrim" onclick=@(()=>DetailOpen=false)></button>
            <div class="player-profile-dialog">
                <div class="player-profile-heading"><div><label class="eyeline localized-text">@StoreText("Карточка игрока","Player card")</label><label class="profile-title">@profile.Name</label><div class="profile-subtitle"><label>@($"{PlayerPositions.Card(profile)} · {PlayerPositions.FullName(PlayerPositions.Card(profile))}")</label><span>·</span><img src="@($"/flags/{profile.CountryCode.ToLowerInvariant()}.svg")" /><label>@profile.Country</label></div></div><button class="profile-close" onclick=@(()=>DetailOpen=false)>✕</button></div>
                <div class="player-profile-body">
                    <div class="profile-showcase">
                        <div class="profile-card-stage"><div class="profile-halo"></div><PlayerCardView Card="@profile" ClubSeed="@C.ClubSeed" CssClass="profile-card" /></div>
                        @if(profile.IsAcademyLoan){<div class="profile-academy-note localized-text"><label>@StoreText("Академия · временный игрок","Academy · temporary player")</label><label>@StoreText("Бесплатно помогает заполнить состав. Его нельзя продать, обменять или улучшить.","Helps fill your lineup for free. Cannot be sold, exchanged or upgraded.")</label></div>}
                        <div class="profile-bio localized-text">
                            <div class="profile-bio-row"><label>@StoreText("Редкость","Rarity")</label><b>@StoreText(UiRussian.Translate(profile.Rarity),profile.Rarity)</b></div>
                            <div class="profile-bio-row"><label>@StoreText("Возраст","Age")</label><b>@(profile.Age>0?profile.Age.ToString():"—")</b></div>
                            <div class="profile-bio-row"><label>@StoreText("Рост","Height")</label><b>@(profile.HeightCm>0?StoreText($"{profile.HeightCm} см",$"{profile.HeightCm} cm"):"—")</b></div>
                            <div class="profile-bio-row"><label>@StoreText("Ведущая нога","Preferred foot")</label><b>@StoreText(profile.Foot=="Left"?"Левая":"Правая",profile.Foot)</b></div>
                            <div class="profile-bio-row"><label>@StoreText("Слабая нога","Weak foot")</label><b>@($"{profile.WeakFoot} ★")</b></div>
                            <div class="profile-bio-row"><label>@StoreText("Финты","Skill moves")</label><b>@($"{profile.SkillMoves} ★")</b></div>
                        </div>
                        @if(Game.ClubPage=="Catalog" && SelectedCatalogCopyId>=0){
                            <label class="profile-fit localized-text">@CopyCaption(profile)</label>
                            @if(CardCollectionView.Copies(C,profile.CardKey).Length>1){<div class="profile-version-tabs localized-text">@foreach(var copy in CardCollectionView.Copies(C,profile.CardKey)){<button class="catalog-owned-copy @(SelectedCatalogCopyId==copy.Id?"chosen":"")" onclick=@(()=>SelectedCatalogCopyId=copy.Id)>@CopyCaption(copy)</button>}</div>}
                        }
                        else if(Game.ClubPage=="Состав" && profileSlot>=0){<label class="profile-fit localized-text">@StoreText($"Стартовый состав · {PlayerPositions.Slot(C.Shape,profileSlot)} · соответствие {Formation.Fit(profile,C.Shape,profileSlot)*100:0}%",$"Starting XI · {PlayerPositions.Slot(C.Shape,profileSlot)} · {Formation.Fit(profile,C.Shape,profileSlot)*100:0}% fit")</label>}
                        else if(Game.ClubPage=="Состав"){<label class="profile-fit localized-text">@StoreText("Запасной · доступен для состава","Reserve · available for the lineup")</label>}
                        @if(Game.ClubPage=="Состав" && profileSlot<0 && !profile.IsAcademyLoan){<div class="profile-copy-actions"><button class="sell-reserve" disabled="@(C.Pending!=null || C.CupWindow)" onclick=@(()=>{Game.SellCard(profile.Id);DetailOpen=false;})>@StoreText($"Продать · {CardEconomy.SellValue(profile)} ◈",$"Sell · {CardEconomy.SellValue(profile)} ◈")</button>@if(C.CanRecycleDuplicate(profile.Id)){<button class="recycle-duplicate" onclick=@(()=>{Game.RecycleDuplicateCard(profile.Id);DetailOpen=false;})>@StoreText($"Обменять дубль: {TrainingGradeName(CardEconomy.DuplicateGrade(profile))} улучшение",$"Exchange duplicate: {TrainingGradeName(CardEconomy.DuplicateGrade(profile))} upgrade")</button>}</div>}
                    </div>
                    <div class="profile-stat-sheet">
                        <div class="profile-sections localized-text">
                            <button class="profile-tab-overview @(ProfileTab==0?"chosen":"")" onclick=@(()=>ProfileTab=0)>@StoreText("Обзор","Overview")</button>
                            <button class="profile-tab-attributes @(ProfileTab==1?"chosen":"")" onclick=@(()=>ProfileTab=1)>@StoreText("Характеристики","Attributes")</button>
                            <button class="profile-tab-skills @(ProfileTab==2?"chosen":"")" onclick=@(()=>ProfileTab=2)><label>@StoreText("Скиллы","Skills")</label><span>@($"{profile.SkillLoadout.Count}/{UniqueSkills.MaxSlots(profile)}")</span></button>
                        </div>
                        <div class="profile-section-content">
                            @if(ProfileTab==0){
                                <div class="profile-section-heading localized-text"><label>@StoreText("Главные атрибуты","Key attributes")</label><span>@StoreText("Максимум 99","Maximum 99")</span></div>
                                <div class="profile-summary">@foreach(var stat in PlayerCardDetails.Summary(profile)){<div class="profile-summary-stat"><div class="summary-main"><div class="summary-icon-gem"><img src="@SummaryIcon(stat.Name)" /></div><div class="summary-copy"><label class="summary-name">@SummaryName(stat.Name)</label><label class="summary-value">@stat.Value</label></div></div><div class="summary-track"><span style="@($"width: {stat.Value}%;")"></span></div></div>}</div>
                                <LegendaryAbilityView Card="@profile" />
                                @if(Game.ClubPage=="Состав" && profileSlot>=0){<div class="profile-instructions"><label class="profile-section-title localized-text">@StoreText($"Задание на матч · {PlayerPositions.Slot(C.Shape,profileSlot)}",$"Match instruction · {PlayerPositions.Slot(C.Shape,profileSlot)}")</label><div>@for(int j=0;j<4;j++){var order=j;var slot=profileSlot;<button class="@(C.Instructions[slot]==j?"chosen":"")" disabled="@(C.Pending!=null)" onclick=@(()=>Game.Instruction(slot,order))><label class="localized-text">@StoreText(j switch{0=>"Сбалансировано",1=>"Держать позицию",2=>"Подключаться в атаку",_=>"Играть шире"},ClubCareer.Orders[j])</label></button>}</div></div>}
                            }
                            else if(ProfileTab==1){
                                <div class="profile-section-heading localized-text"><label>@StoreText("Подробные характеристики","Detailed attributes")</label><span>@StoreText("Максимум 99","Maximum 99")</span></div>
                                <div class="profile-breakdown">@foreach(var group in PlayerCardDetails.Breakdown(profile).Where(s=>profile.Position=="ВР" || s.Group!="Goalkeeping").GroupBy(s=>s.Group).OrderBy(g=>g.Key=="Goalkeeping"?0:1)){<div class="profile-stat-group"><div class="profile-group-heading"><div class="profile-group-icon-gem"><img src="@GroupIcon(group.Key)" /></div><label>@group.Key.ToUpperInvariant()</label></div>@foreach(var stat in group){<div class="profile-stat-row"><label>@stat.Name</label><b>@stat.Value</b></div>}</div>}</div>
                            }
                            else{
                                <div class="profile-equipped-skills localized-text"><div class="profile-section-heading"><label>@StoreText("Скиллы игрока","Equipped skills")</label><span>@($"{profile.SkillLoadout.Count}/{UniqueSkills.MaxSlots(profile)}")</span></div><label class="profile-skill-hint">@(profile.IsAcademyLoan?StoreText("Временных игроков академии нельзя улучшать.","Temporary academy players cannot be upgraded."):StoreText("Карточка улучшений добавляет случайный скилл. Когда все места заняты, один из скиллов заменяется.","An upgrade card grants a random skill. When all slots are filled, one skill is replaced."))</label>@for(int i=0;i<UniqueSkills.MaxSlots(profile);i++){var equipped=SkillAt(profile,i);if(equipped!=null){<CardSkillView Instance="@equipped" />}else if(!profile.IsAcademyLoan){<div class="profile-empty-skill"><label>+</label><label>@StoreText("Свободное место для скилла","Empty skill slot")</label></div>}}</div>
                            }
                        </div>
                    </div>
                </div>
            </div>
        </div>
        }
    }
    @if(OpponentOpen)
    {
        var profile=C.Club(OpponentSlot,OpponentTournament);var shape=Formation.All.First(f=>f.Name==profile.Formation);
        <div class="opponent-backdrop"><div class="opponent-dialog">
            <div class="opponent-heading"><img src="@C.TeamCrest(OpponentSlot,OpponentTournament)" /><div><label class="eyeline">OPPONENT LINEUP</label><label class="opponent-name">@profile.Name</label><label class="muted">@($"{profile.Formation} · OVR {profile.Overall}/99")</label></div><button class="close-opponent" onclick=@(()=>OpponentOpen=false)>×</button></div>
            <div class="opponent-pitch @(shape.Name=="4–2–3–1"?"five-lines":"")"><div class="field-boundary"></div><div class="field-half"></div><div class="field-circle"></div>
            @for(int i=0;i<11;i++){var card=profile.Players[i].Card;<div class="opponent-slot" style="@OpponentSlotStyle(shape,i)"><PlayerCardView Card="@card" ClubSeed="@C.ClubSeed" CssClass="opponent-card" /><label class="opponent-slot-role">@PlayerPositions.Slot(shape,i)</label></div>}
            </div>
        </div></div>
    }
    @if(OpenReport!=null){<CareerMatchReportView Report="@OpenReport" OnClose="@(()=>{OpenReport=null;})" />}
    @if(ArchiveListOpen)
    {
        var reports=C.MatchReports.ToArray();
        <div class="match-history-overlay localized-text"><button class="match-history-scrim" onclick=@(()=>ArchiveListOpen=false)></button><div class="match-history-dialog"><div class="match-history-heading"><label>@StoreText("История матчей","Match history")</label><button class="match-history-close" onclick=@(()=>ArchiveListOpen=false)>✕</button></div>
        <div class="match-history-list">@foreach(var report in reports.Skip(ArchivePage*12).Take(12)){<button class="match-history-row" onclick=@(()=>{OpenReport=report;ArchiveListOpen=false;})><label>@StoreText($"Сезон {report.Season} · {UiRussian.Translate(report.Competition)}",$"Season {report.Season} · {report.Competition}")</label><div><img src="@report.HomeCrest"/><label>@report.HomeName</label><b>@($"{report.HomeGoals}:{report.AwayGoals}")</b><label>@report.AwayName</label><img src="@report.AwayCrest"/></div></button>}</div>
        @if(reports.Length==0){<label class="muted">@StoreText("Здесь появятся ваши сыгранные матчи.","Your completed matches will appear here.")</label>}
        <div class="match-history-pagination"><button disabled="@(ArchivePage==0)" onclick=@(()=>ArchivePage--)>←</button><label>@($"{ArchivePage+1} / {Math.Max(1,(reports.Length+11)/12)}")</label><button disabled="@((ArchivePage+1)*12>=reports.Length)" onclick=@(()=>ArchivePage++)>→</button></div></div></div>
    }
    @if(Game.MatchModeSelection)
    {
        <div class="match-mode-backdrop">
            <div class="match-mode-dialog">
                <label class="eyeline">@($"MATCHDAY / {C.TeamName(0)} VS {Game.PreparationOpponent.ToUpperInvariant()}")</label>
                <label class="match-mode-title">How will you follow the match?</label>
                <label class="muted">Your chosen lineup plays either way. The same result and rewards apply.</label>
                <div class="prematch-faceoff"><div><img src="@C.TeamCrest(0)" /><label>@C.TeamName(0)</label></div><b>VS</b><div><img src="@ClubIdentity.Crest(Game.PreparationOpponent)" /><label>@Game.PreparationOpponent</label></div></div>
                <label class="muted">@Game.PreparationTactics</label>
                <button class="preview-opponent" onclick=@(()=>InspectUpcoming())>View opponent</button>
                <div class="match-mode-options">
                    <button class="match-mode-live" onclick=@(()=>Game.ChooseMatchMode(false))><label class="mode-symbol">◉</label><label class="mode-name">Watch on the pitch</label><label class="mode-description">See the action and coach your team live.</label><label class="mode-arrow">PLAY LIVE →</label></button>
                    @if(!Game.PreparationOpponent.Equals("FRIENDLY MATCH"))
                    {
                        <button class="match-mode-text" onclick=@(()=>Game.ChooseMatchMode(true))><label class="mode-symbol">≡</label><label class="mode-name">Live text commentary</label><label class="mode-description">Follow every key moment in a fast broadcast.</label><label class="mode-arrow">AUTO MATCH →</label></button>
                    }
                </div>
                <button class="mode-back" onclick=@(()=>Game.ReturnToLineup())>← Back to lineup</button>
            </div>
        </div>
    }
    }
}
@if(Game?.ClubOpen==true && !DetailOpen && !OpponentOpen && !SkillLibraryOpen && !ArchiveListOpen && OpenReport==null && !PackRevealActive && StoreOfferIndex<0 && DragCardId<0 && TrainingAnimation==0)
{
    <ClubContextHelp Game="@Game" />
}
@if(Game?.ClubOpen==true && Game.TutorialStep>=0 && !Game.GameSettingsOpen)
{
    var tour=ClubTour.Steps[Math.Clamp(Game.TutorialStep,0,ClubTour.Steps.Length-1)];
    <div class="club-tour-shade"></div>
    <div class="club-tour-card localized-text">
        <div class="tour-topline"><div><img src="@($"/ui-icons/ui-bold-nav-{tour.Icon}.svg")" /><label>@(GamePreferences.Russian?"ЗНАКОМСТВО С ИГРОЙ":"WELCOME TO SOCER")</label></div><button class="tour-skip" onclick=@(()=>Game.FinishTutorial())>×</button></div>
        <label class="tour-title">@(GamePreferences.Russian?tour.RussianTitle:tour.EnglishTitle)</label>
        <label class="tour-body">@(GamePreferences.Russian?tour.RussianBody:tour.EnglishBody)</label>
        <div class="tour-tip"><span>✦</span><label>@(GamePreferences.Russian?tour.RussianTip:tour.EnglishTip)</label></div>
        <div class="tour-actions">
            <button class="tour-practice" disabled="@(!Game.CanStartMatchTutorial)" onclick=@(()=>Game.StartMatchTutorial())><img src="/ui-icons/ui-bold-nav-play.svg" /><div><label>@(GamePreferences.Russian?"Начать учебный матч":"Start training match")</label><label>@(GamePreferences.Russian?"Попробуйте команды на поле":"Try the pitch commands")</label></div><span>→</span></button>
            <button class="tour-next" onclick=@(()=>Game.FinishTutorial())>@(GamePreferences.Russian?"Перейти в клуб":"Go to my club")</button>
        </div>
    </div>
}
@if(Game?.ClubOpen==true && PackRevealActive && Game.RevealedPack!=null)
{
    @if(SelectedOffer.UpgradeOnly)
    {
        <UpgradeCapsuleView @key="Game.RevealedPack" Opening="@Game.RevealedPack" StartedAt="@PackRevealStartedAt" OnClose="@ClosePackReveal" OnInventory="@(()=>{ClosePackReveal();Game.ClubPage="Тренировки";})" />
    }
    else
    {
    <PackOpeningView @key="Game.RevealedPack" @ref="PackView" Opening="@Game.RevealedPack" PackArt="@PackArt(SelectedPack)" PackName="@PackName(SelectedPack)" ClubSeed="@C.ClubSeed" Preview="@PackPreviewMode" StartedAt="@PackRevealStartedAt" OnClose="@ClosePackReveal" OnInventory="@(()=>{ClosePackReveal();Game.ClubPage="Состав";})" />
    }
}
</root>

@code {
    protected override void OnTreeBuilt(){base.OnTreeBuilt();UiRussian.Apply(Panel);}
    string PreviousPage;
    bool WasOpen;
    int ResetPageScrollFrames;
    float PageEnteredAt;
    protected override void OnUpdate()
    {
        bool open=Game?.ClubOpen==true;
        if(open && Game.TutorialStep>=0)
        {
            DetailOpen=OpponentOpen=SkillLibraryOpen=ArchiveListOpen=false;OpenReport=null;StoreOfferIndex=-1;
            if(PackRevealActive)ClosePackReveal();
        }
        if(TrainingAnimation==1 && Time.Now>=TrainingRevealAt)TrainingAnimation=2;
        if(TrainingAnimation!=0 && Time.Now>=TrainingFeedbackUntil){TrainingAnimation=0;ConsumedTraining=null;BeforeUpgradePlayer=null;}
        if(open && TrainingItemId>=0 && ActiveTraining==null)TrainingItemId=-1;
        if(!open || Game.ClubPage!="Тренировки" || Game.GameSettingsOpen || UpgradeBusy || ActiveTraining==null ||
            TrainingDiscardItemId!=TrainingItemId || !C.CanDiscardTrainingCard(TrainingItemId))TrainingDiscardItemId=-1;
        if(PackRevealActive && Game.RevealedPack==null)ClosePackReveal();
        if(open && (!WasOpen || PreviousPage!=Game.ClubPage)){PageEnteredAt=Time.Now;ResetPageScrollFrames=2;}
        // Wait for the new page's layout before resetting a reused scroll panel.
        var pageBody=Panel?.Descendants.FirstOrDefault(p=>p.HasClass("club-body") && p.GetAttribute("data-club-page","")==Game?.ClubPage);
        if(open && ResetPageScrollFrames>0 && pageBody!=null && pageBody.Box.Rect.Width>0 && --ResetPageScrollFrames==0)
        {
            foreach(var panel in pageBody.Descendants.Where(p=>p.HasScrollY && p.Box.Rect.Width>0 && p.Box.Rect.Height>0))
                panel.ScrollTo(Vector2.Zero);
        }
        if(open && (!WasOpen || PreviousPage!=Game.ClubPage) && Game.ClubPage=="Equipment")
        {PreviewKitId=C.EquippedKitId;PreviewBallId=C.EquippedBallId;}
        if(!open || Game.ClubPage is not ("Состав" or "Catalog"))DetailOpen=false;
        if(!open){OpenReport=null;ArchiveListOpen=false;}
        if(!open || Game.ClubPage!="Кубок")ViewedCupId="";
        if(!open || Game.ClubPage!="Карточки")StoreOfferIndex=-1;
        WasOpen=open;PreviousPage=Game?.ClubPage;
    }
    MatchController cachedGame;
    MatchController Game
    {
        get
        {
            if(cachedGame?.GameObject?.IsValid!=true || cachedGame.Scene!=Scene)
                cachedGame=Scene.GetAllComponents<MatchController>().FirstOrDefault();
            return cachedGame;
        }
    }
    ClubCareer C=>Game.Career;
    int SelectedSlot {get;set;}
    int SelectedCardId {get;set;}
    bool DetailOpen {get;set;}
    int ProfileTab {get;set;}
    string ReviewLegendId=PlayerAppearance.MbappeId;
    PlayerCard ReviewLegend=>PlayerCatalog.LegendaryCards.FirstOrDefault(p=>p.CatalogId==ReviewLegendId)??PlayerCatalog.LegendaryCards.First();
    IEnumerable<PlayerCard> ReviewLegendVersions=>PlayerCatalog.All.Any(p=>p.CatalogId==ReviewLegend.CatalogId)?new[]{PlayerCatalog.Find(ReviewLegend.CatalogId),ReviewLegend}:new[]{ReviewLegend};
    int DetailSlot=>Array.IndexOf(C.Lineup,Selected.Id);
    Panel ClubRoot {get;set;}
    Panel DragGhost {get;set;}
    Panel BenchArea {get;set;}
    Panel SquadPitch {get;set;}
    Panel BenchStrip {get;set;}
    string BenchSearch="",BenchFilter="All";
    int DragCardId=-1,DropSlot=-1;
    string DragMessage="";
    float DragMessageUntil;
    PlayerCard DragCard=>C.Cards.FirstOrDefault(c=>c.Id==DragCardId);
    string BenchSummary
    {
        get
        {
            int total=0,academy=0;
            foreach(var player in C.Cards)
                if(!C.Lineup.Contains(player.Id)){total++;if(player.IsAcademyLoan)academy++;}
            return StoreText($"{total} игроков",$"{total} players")+(academy>0?StoreText($" · акад. {academy}",$" · academy {academy}"):"");
        }
    }
    PlayerCard[] FilteredBench
    {
        get
        {
            // Count copies once, rather than rescanning a growing collection for every card.
            var copies=BenchFilter=="DUP"?C.Cards.GroupBy(p=>p.CardKey).Where(g=>g.Count()>1).Select(g=>g.Key).ToHashSet():null;
            return C.Cards.Where(p=>!C.Lineup.Contains(p.Id) && (copies!=null?copies.Contains(p.CardKey):BenchMatches(p)) &&
                (string.IsNullOrWhiteSpace(BenchSearch) || p.Name.Contains(BenchSearch,StringComparison.OrdinalIgnoreCase) || p.Country.Contains(BenchSearch,StringComparison.OrdinalIgnoreCase))).OrderByDescending(p=>p.Overall).ToArray();
        }
    }
    bool BenchMatches(PlayerCard p)=>BenchFilter switch{"GK"=>p.Position=="ВР","DEF"=>p.Position is "КЗ" or "ЦЗ","MID"=>p.Position is "ЦП" or "КП","ATT"=>p.Position=="НП",_=>true};
    void BeginSquadDrag(int id){if(!Game.CanEditStartingLineup)return;DragCardId=id;MoveSquadDrag();}
    void MoveSquadDrag(){if(DragCardId>=0)DropSlot=PitchDropSlot();}
    void EndSquadDrag()
    {
        if(DragCardId<0)return;
        int source=DragCardId,target=PitchDropSlot();
        if(target<0 && C.Lineup.Contains(source) && BenchArea!=null && PointerInside(BenchArea))
        {
            Game.RemoveStartingCard(Array.IndexOf(C.Lineup,source));
            DragMessage="Fill all 11 positions before starting a match.";DragMessageUntil=Time.Now+3;DragCardId=-1;DropSlot=-1;return;
        }
        if(target>=0 && C.Lineup[target]!=source)
        {
            var card=C.Cards.FirstOrDefault(c=>c.Id==source);
            if(card!=null && (target==0)==(card.Position=="ВР"))
            {Game.AssignCard(target,source);SelectedSlot=target;SelectedCardId=source;DragMessage=$"{card.Name} moved to {PlayerPositions.Slot(C.Shape,target)}.";}
            else DragMessage="Only goalkeepers can take the goalkeeper position.";
        }
        else DragMessage="Drop a card on another player or position to swap.";
        DragMessageUntil=Time.Now+3;DragCardId=-1;DropSlot=-1;
    }
    static bool PointerInside(Panel panel)
    {var p=panel.MousePosition;return p.x>=0 && p.y>=0 && p.x<=panel.Box.Rect.Width && p.y<=panel.Box.Rect.Height;}
    int PitchDropSlot()
    {
        if(SquadPitch==null || !PointerInside(SquadPitch))return -1;
        float best=75*75;int slot=-1;bool insideCard=false;
        for(int i=0;i<11;i++)
        {
            var button=SquadPitch.Descendants.FirstOrDefault(v=>v.HasClass($"squad-position-{i}"));
            if(button==null)continue;
            var p=button.MousePosition;var center=new Vector2(button.Box.Rect.Width*.5f,button.Box.Rect.Height*.5f);
            float d=(p-center).LengthSquared;bool hit=PointerInside(button);
            // Hit the displayed card, including its lower half. Formation
            // coordinates place the card's corner and are not a drop target.
            if((hit && !insideCard) || (hit==insideCard && d<best)){insideCard=hit;best=d;slot=i;}
        }
        return slot;
    }
    string DragGhostStyle()
    {
        // MousePosition is measured in surface pixels, while style lengths use
        // reference UI pixels. Convert once so the ghost follows the cursor at
        // every UI scale, including the editor's embedded game viewport.
        var p=(ClubRoot?.MousePosition??Vector2.Zero)*(ClubRoot?.ScaleFromScreen??1f);
        return FormattableString.Invariant($"left:{p.x:0.##}px;top:{p.y:0.##}px;");
    }
    static PackReward EquipmentReward(string kind,string id,string name)=>new(){Kind=kind,CosmeticId=id,Name=name};
    string PreviewKitId="north",PreviewBallId="classic";
    public string[] PortraitSheetIds {get;set;}=Array.Empty<string>();
    string CatalogSearch="";
    string CatalogTier="All tiers";
    string CatalogSort="rating";
    string CatalogCountry="All countries";
    void SelectCatalogCountry(string country){CatalogCountry=country;CatalogPage=0;}
    string CatalogPosition="All positions";
    bool CatalogOwned;
    bool CatalogSkills;
    void SelectCatalogSection(bool skills){CatalogSkills=skills;DetailOpen=false;SkillLibraryOpen=false;}
    int CatalogPage;
    string SelectedCatalogKey="";
    int SelectedCatalogCopyId=-1;
    void InspectCatalog(PlayerCard card,bool owned){SelectedCatalogKey=card.CardKey;SelectedCatalogCopyId=owned?card.Id:-1;ProfileTab=0;DetailOpen=true;}
    string CopyCaption(PlayerCard card)=>StoreText($"Копия {CardCollectionView.CopyNumber(C,card)} · скиллы {card.SkillLoadout.Count}/{UniqueSkills.MaxSlots(card)}",$"Copy {CardCollectionView.CopyNumber(C,card)} · skills {card.SkillLoadout.Count}/{UniqueSkills.MaxSlots(card)}");
    ArchivedClubMatch OpenReport;
    bool ArchiveListOpen;
    int ArchivePage;
    void ShowMatchReport(ClubFixture fixture){OpenReport=C.MatchReport(fixture);ArchiveListOpen=false;}

    System.Collections.Generic.IEnumerable<PlayerCard> FilteredCatalog=>PlayerCatalog.SortCardVariants(CardCollectionView.Cards(C,CatalogOwned).Where(p=>
        (CatalogTier=="All tiers" || p.Rarity.Equals(CatalogTier,StringComparison.OrdinalIgnoreCase)) &&
        (CatalogCountry=="All countries" || p.Country==CatalogCountry) &&
        (CatalogPosition=="All positions" || PlayerPositions.Card(p)==CatalogPosition) &&
        (string.IsNullOrWhiteSpace(CatalogSearch) || p.Name.Contains(CatalogSearch,StringComparison.OrdinalIgnoreCase) || CatalogCountryNames.Matches(p.Country,CatalogSearch))),CatalogSort=="type");
    PlayerCard ScoutPreview;
    int SelectedPack;
    int BuyQuantity=1;
    bool StoreInventory;
    bool StoreCupPacks;
    bool StoreCapsules;
    int StoreOfferIndex=-1;
    static string StoreText(string ru,string en)=>GamePreferences.Russian?ru:en;
    static string PackArt(int index)=>ScoutPacks.All[index].UpgradeOnly?$"/store-packs/{(index==8?"upgrade-silver":"upgrade-gold")}.svg":ScoutPacks.All[index].UsesCupTokens?$"/store-packs/{ScoutPacks.All[index].Name.ToLowerInvariant()}.svg":$"/textures/store/{ScoutPacks.All[index].Name.ToLowerInvariant()}-pack-v1.png";
    static string PackName(int index)=>ScoutPacks.All[index].UpgradeOnly?StoreText(index==8?"Серебряная капсула":"Золотая капсула",index==8?"Silver capsule":"Gold capsule"):ScoutPacks.All[index].UsesCupTokens?StoreText("Кубковый пак · ","Cup pack · ")+StoreLeagueName(ScoutPacks.All[index].UnlockDivision):StoreText(new[]{"Серебряный пак","Золотой пак","Алмазный пак"}[Math.Clamp(index,0,2)],ScoutPacks.All[index].Name+" pack");
    static string StoreLeagueName(int division)=>StoreText(new[]{"Третья лига","Вторая лига","Первая лига","Национальная лига","Премьер-лига"}[Math.Clamp(division-1,0,4)],LeagueName(division));
    static string PackDescription(int index)
    {
        var offer=ScoutPacks.All[index];
        if(offer.UpgradeOnly)return StoreText("Одна карточка улучшения. Серебро и золото повышают шанс золотого скилла при применении.","One upgrade card. Silver and gold upgrades increase the gold skill chance when applied.");
        if(offer.UsesCupTokens)return offer.Legendary>0
            ?StoreText("Только золотые, элитные и легендарные футболисты. Повышенный шанс редких карточек; легенды доступны начиная с Национальной лиги.","Only gold, elite and legendary footballers. Higher rare-card chances; legendary editions start with the National League pack.")
            :StoreText("Только золотые и элитные футболисты. С каждой лигой шанс элиты растёт. Легенды доступны в паках Национальной и Премьер-лиги.","Only gold and elite footballers. The elite chance rises with each league. Legendary editions are available in National and Premier League packs.");
        return StoreText(new[]{"Пополнение клуба: преимущественно бронзовые игроки, шанс серебра и редкое золото.","Усиление состава: серебряные и золотые игроки, шанс элитной карточки.","Высший класс: золотые и элитные игроки, больше дополнений высокого качества."}[Math.Clamp(index,0,2)],new[]{"Build your club: mostly bronze players, a chance of silver and rare gold.","Strengthen your squad: silver and gold players with a chance of elite.","Top class: gold and elite players, more high-quality extras."}[Math.Clamp(index,0,2)]);
    }
    static string StoreCurrencyAmount(ScoutPackOffer offer,int amount)=>offer.UsesCupTokens?StoreText($"{amount:N0} кубков",$"{amount:N0} cup tokens"):$"{amount:N0} ◈";
    int StoreOwnedCount(bool cupPacks)=>ScoutPacks.All.Select((offer,index)=>!offer.UpgradeOnly && offer.UsesCupTokens==cupPacks?C.OwnedPacks(index):0).Sum();
    string CupPrizeSummary(CupTournament cup)=>StoreText($"Победа: +{cup.RoundPrize} ◈ и +{CupEconomy.MatchWinReward(C.Division)} кубков · Трофей: +{cup.TrophyPrize} ◈",$"Win: +{cup.RoundPrize} ◈ and +{CupEconomy.MatchWinReward(C.Division)} cup tokens · Trophy: +{cup.TrophyPrize} ◈");
    static string TrainingGradeName(int grade)=>StoreText(new[]{"Бронза","Серебро","Золото"}[Math.Clamp(grade,1,3)-1],new[]{"Bronze","Silver","Gold"}[Math.Clamp(grade,1,3)-1]);
    string DuplicateRewardText(PackReward item)=>item.Player!=null?StoreText("ДУБЛЬ · отдельная копия добавлена в клуб","DUPLICATE · a separate copy added to your club"):StoreText($"ДУБЛЬ · компенсация +{item.Coins} ◈",$"DUPLICATE · compensation +{item.Coins} ◈");
    string PackRewardDetail(PackReward item)=>item.Kind=="training"
        ?StoreText("Добавляет случайный скилл или заменяет один из текущих.","Adds a random skill or replaces an existing one.")
        :StoreText(UiRussian.Translate(item.Detail??""),item.Detail??"");
    void SetStoreTab(bool inventory){StoreInventory=inventory;StoreOfferIndex=-1;}
    int CapsuleOwnedCount=>ScoutPacks.All.Select((offer,index)=>offer.UpgradeOnly?C.OwnedPacks(index):0).Sum();
    int VisibleStoreOwnedCount=>StoreCapsules?CapsuleOwnedCount:StoreOwnedCount(StoreCupPacks);
    void SetStoreCurrency(bool cups){StoreCapsules=false;StoreCupPacks=cups;StoreOfferIndex=-1;}
    void SetStoreCapsules(){StoreCapsules=true;StoreCupPacks=false;StoreOfferIndex=-1;}
    void ShowStoreOffer(int pack){StoreOfferIndex=pack;BuyQuantity=1;}
    string StoreBlockReason(int pack)=>C.Pending!=null?StoreText("Завершите текущий матч.","Finish your current match."):C.CupWindow?StoreText("Доступно после кубка.","Available after the cup."):C.Division<ScoutPacks.All[pack].UnlockDivision?StoreText($"Нужна лига: {StoreLeagueName(ScoutPacks.All[pack].UnlockDivision)}",$"Required league: {StoreLeagueName(ScoutPacks.All[pack].UnlockDivision)}"):ScoutPacks.All[pack].UsesCupTokens?StoreText("Недостаточно кубков.","Not enough cup tokens."):StoreText("Недостаточно монет.","Not enough coins.");
    string StoreFeedback="";
    float StoreFeedbackUntil;
    void BuyStorePacks(int pack){if(Game.BuyPacks(pack,BuyQuantity)){StoreFeedback=StoreText($"Куплено: {BuyQuantity}",$"Purchased: {BuyQuantity}");StoreFeedbackUntil=Time.Now+3;StoreOfferIndex=-1;StoreInventory=true;}}
    void OpenStorePack(int pack){SelectedPack=pack;ScoutPreview=null;ShowScoutResult=false;OpenScout();}
    string PackSpaceHint(int pack)=>C.PackCapacityFailure(pack) switch
    {
        "players"=>StoreText("Недостаточно места для футболистов. Продайте запасные карточки; пак останется в инвентаре.","Not enough player space. Sell reserve cards; the pack stays in inventory."),
        "training"=>StoreText("Недостаточно места для улучшений. Примените или спишите ненужные карточки в «Мой клуб → Улучшения»; пак сохранён.","Not enough upgrade space. Apply or discard unwanted cards in My club → Upgrades; the pack is kept."),
        _=>""
    };
    static string NavKey(string page)=>page switch{"Главная"=>"club","Лига"=>"league","Кубок"=>"cup","Карточки"=>"store","Missions"=>"missions",_=>"catalog"};
    static string NavName(string page)=>page switch{"Главная"=>"My Club","Лига"=>"League","Кубок"=>"Cups","Карточки"=>"Store","Missions"=>"Missions",_=>"Catalog"};
    System.Collections.Generic.IEnumerable<ClubFixture> RecentResults=>C.League.Concat(C.Tournaments.SelectMany(t=>t.Games)).Where(f=>f.Played && (f.Home==0 || f.Away==0)).OrderByDescending(f=>f.PlayedSequence).ThenByDescending(f=>C.League.Contains(f)?f.Round:(C.Tournaments.FirstOrDefault(t=>t.Games.Contains(f))?.OpensAfterRound??0)+f.Round*.1).Take(5);
    static string ResultClass(ClubFixture fixture)=>fixture.ResultFor(0) switch{1=>"won",-1=>"lost",_=>"draw"};
    static string CupPlace(CupSeasonResult result)=>GamePreferences.Russian
        ?(result.PlaceFrom==result.PlaceTo?$"{result.PlaceFrom}-е место":$"{result.PlaceFrom}–{result.PlaceTo}-е место")
        :(result.PlaceFrom==result.PlaceTo?result.PlaceFrom==1?"1st place":"2nd place":result.PlaceFrom==3?"3rd–4th place":"5th–8th place");

    bool ShowScoutResult;
    bool PackRevealActive;
    PackOpeningView PackView;
    bool PackPreviewMode;
    float PackRevealStartedAt;
    public int ReviewAngle=3;
    public float? ReviewFacingOverride;
    public bool ReviewLowDetail,ReviewCloseupOverride;
    public bool ReviewClay;
    public string[] PortraitReviewIds=new[]{PlayerAppearance.HaalandId,PlayerAppearance.MessiId};
    int PackInspectIndex=-1;
    System.Collections.Generic.IReadOnlyList<PackReward> PackRewards=>new PackOpeningPresentation(Game.RevealedPack).Rewards;
    int PackRevealCount=>!PackRevealActive?0:PackView?.RevealedCount??0;
    PackReward PackFocusReward=>PackRevealCount==0?null:PackRewards[PackInspectIndex>=0 && PackRevealCount==PackRewards.Count?PackInspectIndex:PackRevealCount-1];
    ScoutPackOffer SelectedOffer=>ScoutPacks.All[Math.Clamp(SelectedPack,0,ScoutPacks.All.Length-1)];
    float ScoutRevealAt;
    PlayerCard ScoutCard=>ScoutPreview??(ShowScoutResult?Game.RevealedCard:null);
    bool ScoutOpening=>ScoutCard!=null && Time.Now<ScoutRevealAt;
    bool ScoutVisible=>ScoutCard!=null && !ScoutOpening;
    bool CanOpenScout=>!PackRevealActive && ScoutPreview==null && !ScoutOpening && C.CanOpenOwnedPack(SelectedPack);
    void SelectPack(int index){if(ScoutOpening)return;SelectedPack=Math.Clamp(index,0,ScoutPacks.All.Length-1);ScoutPreview=null;ShowScoutResult=false;}
    void OpenScout()
    {
        if(!CanOpenScout)return;
        Game.Pack(SelectedPack);
        ShowScoutResult=Game.RevealedPack?.Items.Count>0;
        if(ShowScoutResult){PackRevealActive=true;PackPreviewMode=false;PackRevealStartedAt=Time.Now;PackInspectIndex=-1;}
    }
    void AdvancePackReveal()=>PackView?.RevealNext();
    void RevealAllPackItems()=>PackView?.RevealAll();
    void InspectPackItem(int index){}
    void ClosePackReveal(){PackView?.StopPresentation();PackRevealActive=false;PackPreviewMode=false;PackInspectIndex=-1;ShowScoutResult=false;ScoutPreview=null;}
    void VisitScoutPlayer(string page){SelectedCardId=ScoutCard.Id;Game.ClubPage=page;}
    public void PreviewScout(PlayerCard card,bool animate=false){PackRevealActive=false;PackPreviewMode=false;ScoutPreview=card;ShowScoutResult=card!=null;ScoutRevealAt=animate?Time.Now+2.5f:0;}
    public void PreviewPack(PackOpening opening,int revealCount=5)
    {ScoutPreview=null;SelectedPack=opening?.PackIndex??0;ShowScoutResult=opening!=null;PackRevealActive=opening!=null;PackPreviewMode=opening!=null;PackInspectIndex=-1;PackRevealStartedAt=Time.Now-(revealCount>0?new PackOpeningPresentation(opening).CompleteAt:0);ScoutRevealAt=0;}
    int TrainingGrade=0;
    int TrainingItemId=-1;
    int TrainingPage,TrainingDiscardItemId=-1;
    const int TrainingPageSize=24;
    TrainingCardItem ActiveTraining=>C.TrainingInventory.FirstOrDefault(i=>i.Id==TrainingItemId);
    int FilteredTrainingCount=>C.TrainingInventory.Count(i=>TrainingGrade==0 || i.Grade==TrainingGrade);
    int TrainingPageCount=>Math.Max(1,(FilteredTrainingCount+TrainingPageSize-1)/TrainingPageSize);
    int EffectiveTrainingPage=>Math.Clamp(TrainingPage,0,TrainingPageCount-1);
    string TrainingPageLabel=>FilteredTrainingCount==0?StoreText("Нет карточек","No cards"):
        $"{EffectiveTrainingPage*TrainingPageSize+1}–{Math.Min((EffectiveTrainingPage+1)*TrainingPageSize,FilteredTrainingCount)} / {FilteredTrainingCount}";
    System.Collections.Generic.IEnumerable<TrainingCardItem> TrainingCards=>C.TrainingInventory.Where(i=>TrainingGrade==0 || i.Grade==TrainingGrade)
        .OrderByDescending(i=>i.Grade).ThenBy(i=>i.Id).Skip(EffectiveTrainingPage*TrainingPageSize).Take(TrainingPageSize);
    void SetTrainingGrade(int grade)
    {
        if(UpgradeBusy)return;
        TrainingGrade=Math.Clamp(grade,0,3);TrainingPage=0;CancelTrainingDiscard();
        if(ActiveTraining!=null && TrainingGrade!=0 && ActiveTraining.Grade!=TrainingGrade)TrainingItemId=-1;
    }
    void ChangeTrainingPage(int delta){if(!UpgradeBusy){TrainingPage=Math.Clamp(EffectiveTrainingPage+delta,0,TrainingPageCount-1);CancelTrainingDiscard();}}
    string TrainingItemLabel(TrainingCardItem item)=>StoreText("Карточка улучшения","Upgrade card")+" · "+TrainingGradeName(item.Grade);
    bool CanDiscardTraining=>!UpgradeBusy && ActiveTraining!=null && C.CanDiscardTrainingCard(ActiveTraining.Id);
    void RequestTrainingDiscard(){if(CanDiscardTraining)TrainingDiscardItemId=ActiveTraining.Id;}
    void CancelTrainingDiscard()=>TrainingDiscardItemId=-1;
    void ConfirmTrainingDiscard()
    {
        if(!CanDiscardTraining || TrainingDiscardItemId!=TrainingItemId)return;
        if(!Game.DiscardTrainingItem(TrainingDiscardItemId)){CancelTrainingDiscard();return;}
        TrainingItemId=-1;CancelTrainingDiscard();TrainingPage=Math.Clamp(TrainingPage,0,TrainingPageCount-1);
    }
    bool SkillLibraryOpen;
    int SkillLibraryGrade=1;
    static SkillInstance SkillAt(PlayerCard player,int slot)=>player.SkillLoadout!=null && slot>=0 && slot<player.SkillLoadout.Count?player.SkillLoadout[slot]:null;
    void ChooseUpgradePlayer(PlayerCard player){if(UpgradeBusy || player.IsAcademyLoan)return;SelectedCardId=player.Id;CancelTrainingDiscard();}
    void ChooseTrainingCard(TrainingCardItem item){if(UpgradeBusy)return;TrainingItemId=item.Id;CancelTrainingDiscard();}
    bool CanApplyTraining=>!UpgradeBusy && !Selected.IsAcademyLoan && ActiveTraining!=null && C.CanUseTrainingCard(ActiveTraining.Id,Selected.Id);
    bool UpgradeReplacesSkill=>Selected.SkillLoadout.Count>=UniqueSkills.MaxSlots(Selected);
    bool UpgradeGoldAtRisk=>UpgradeReplacesSkill && Selected.SkillLoadout.Any(skill=>skill.Grade>=2);
    float TrainingFeedbackUntil;
    float TrainingRevealAt;
    int TrainingAnimation;
    int TrainedPlayer;
    SkillInstance PreviousUpgrade,GrantedUpgrade;
    TrainingCardItem ConsumedTraining;
    PlayerCard BeforeUpgradePlayer;
    bool UpgradeBusy=>TrainingAnimation!=0;
    TrainingCardItem UpgradeVisualTraining=>UpgradeBusy?ConsumedTraining:ActiveTraining;
    PlayerCard UpgradeDisplayPlayer=>TrainingAnimation==1 && BeforeUpgradePlayer?.Id==Selected.Id?BeforeUpgradePlayer:Selected;
    bool TrainingGlow=>TrainingAnimation==2 && GrantedUpgrade!=null && TrainedPlayer==Selected.Id;
    string TrainingReason=>C.HasRelegationChoice?StoreText("Сначала выберите последствие вылета.","Resolve your relegation choice first."):Selected.IsAcademyLoan?StoreText("Временных игроков академии нельзя улучшать.","Temporary academy players cannot be upgraded."):GamePreferences.Russian?
        (C.CupWindow?"Улучшения доступны после кубка.":C.Pending!=null?"Сначала завершите матч.":UpgradeBusy?"":ActiveTraining==null?"Карточки улучшений можно получить в паках.":"Скилл подходит игровой роли этого футболиста."):
        (C.CupWindow?"Upgrades resume after this cup run.":C.Pending!=null?"Finish the current match before upgrading.":UpgradeBusy?"":ActiveTraining==null?"Find more upgrade cards in packs.":"The skill matches this player's role.");
    void ApplyTraining()
    {
        if(!CanApplyTraining)return;
        CancelTrainingDiscard();
        var item=ActiveTraining;var before=PlayerCatalog.Clone(Selected);before.Id=Selected.Id;
        if(!Game.UseTrainingItem(item.Id,Selected.Id))return;
        BeforeUpgradePlayer=before;ConsumedTraining=item;TrainingAnimation=1;
        TrainedPlayer=Selected.Id;TrainingRevealAt=Time.Now+.65f;TrainingFeedbackUntil=Time.Now+1.9f;
        PreviousUpgrade=C.LastSkillUpgrade?.Previous;GrantedUpgrade=C.LastSkillUpgrade?.Granted;
        TrainingItemId=-1;
    }
    ClubFixture Upcoming=>C.Pending!=null?C.ActiveFixture:C.Next(true)??C.Next(false);
    string ViewedCupId="";
    CupTournament ViewedCup=>C.Tournaments.FirstOrDefault(t=>t.Id==ViewedCupId && CanInspectCup(t));
    bool CanInspectCup(CupTournament cup)=>CanViewCup(cup) || cup!=null && (cup.Finished || cup.Eliminated) && cup.Games.Any(f=>f.Played);
    bool CanViewCup(CupTournament cup)=>cup!=null && !cup.Finished && !cup.Eliminated && cup.NextNorth!=null &&
        (C.Pending!=null?C.Pending.Cup && C.MatchCup?.Id==cup.Id:C.DueCup?.Id==cup.Id);
    void NavigateClubPage(string page)
    {
        ViewedCupId="";Game.ClubPage=page;ResetPageScrollFrames=2;
    }
    public bool HotkeyModalOpen=>DetailOpen || OpponentOpen || SkillLibraryOpen || ArchiveListOpen || OpenReport!=null ||
        PackRevealActive || StoreOfferIndex>=0 || DragCardId>=0 || TrainingAnimation!=0 || TrainingDiscardItemId>=0 ||
        Panel.Descendants.OfType<CatalogCountryPicker>().Any(p=>p.Open);
    public void InspectHotkeyPlayer(int id)
    {
        NavigateClubPage("Состав");
        if(C.Cards.Any(c=>c.Id==id)){SelectedCardId=id;ProfileTab=0;DetailOpen=true;}
    }
    public bool HandleHotkey(string id)
    {
        if(Game?.ClubOpen!=true || Game.QuickMatchRunning)return false;
        if(Game.QuickBroadcastOpen)
        {if(id=="app.confirm" && Game.Match.Finished && !Game.AwaitingCareerRoundResults){Game.OpenBroadcastReport();return true;}return false;}
        if(id=="app.back")
        {
            var picker=Panel.Descendants.OfType<CatalogCountryPicker>().FirstOrDefault(p=>p.Open);
            if(picker?.ActivePopup!=null){picker.ActivePopup.Delete(true);return true;}
            if(DragCardId>=0){DragCardId=DropSlot=-1;return true;}
            if(TrainingDiscardItemId>=0){CancelTrainingDiscard();return true;}
            if(StoreOfferIndex>=0){StoreOfferIndex=-1;return true;}
            if(PackRevealActive){ClosePackReveal();return true;}
            if(OpenReport!=null){OpenReport=null;return true;}
            if(ArchiveListOpen){ArchiveListOpen=false;return true;}
            if(SkillLibraryOpen){SkillLibraryOpen=false;return true;}
            if(DetailOpen){DetailOpen=false;return true;}
            if(OpponentOpen){OpponentOpen=false;return true;}
            if(TrainingAnimation!=0)return true;
            return false;
        }
        if(id=="app.confirm" && PackRevealActive){AdvancePackReveal();return true;}
        if(id=="ui.search")
        {
            var search=Panel.Descendants.OfType<TextEntry>().FirstOrDefault(p=>p.IsVisible && p.Box.Rect.Width>0 && p.Box.Rect.Height>0);
            if(search==null)return false;search.Focus();return true;
        }
        if(id is "ui.previous_page" or "ui.next_page")
        {
            int step=id=="ui.previous_page"?-1:1;
            if(ArchiveListOpen){ArchivePage=Math.Clamp(ArchivePage+step,0,Math.Max(0,(C.MatchReports.Count()-1)/12));return true;}
            if(!HotkeyModalOpen && Game.ClubPage=="Catalog" && !CatalogSkills){CatalogPage=Math.Clamp(CatalogPage+step,0,Math.Max(0,(FilteredCatalog.Count()-1)/24));return true;}
            if(!HotkeyModalOpen && Game.ClubPage=="Тренировки"){ChangeTrainingPage(step);return true;}
            return false;
        }
        if(HotkeyModalOpen)return false;
        if(Game.TutorialStep>=0)
        {if(id=="app.confirm"){Game.NextTutorialStep();return true;}return false;}
        if(Game.MatchModeSelection)
        {if(id=="app.confirm"){Game.ChooseMatchMode(false);return true;}if(id=="club.mode_text" && !Game.MediaLeagueActive){Game.ChooseMatchMode(true);return true;}return false;}
        if(Game.PreparingMatch)
        {if(id=="app.confirm" && C.HasCompleteLineup){Game.ConfirmPreparation();return true;}return false;}
        string page=id switch
        {
            "club.overview"=>"Главная","club.squad"=>"Состав","club.training"=>"Тренировки","club.equipment"=>"Equipment",
            "club.league"=>"Лига","club.cups"=>"Кубок","club.missions"=>"Missions","club.store"=>"Карточки","club.catalog"=>"Catalog",_=>null
        };
        if(page!=null){NavigateClubPage(page);return true;}
        if(id=="club.friendly" && C.Pending==null && !C.CupWindow){Game.PrepareFriendly();return true;}
        if(id=="club.opponent" && Upcoming!=null){InspectUpcoming();return true;}
        if(id=="app.confirm" && Game.ClubPage=="Главная"){PlayUpcoming();return true;}
        if(id=="player.inspect" && Game.ClubPage=="Состав"){SelectReserve(Selected.Id);return true;}
        return false;
    }
    void OpenCup(CupTournament cup){ViewedCupId=CanInspectCup(cup)?cup.Id:"";Game.ClubPage="Кубок";}
    string CupStatus(CupTournament cup)=>cup.Won?(GamePreferences.Russian?"КУБОК ВЫИГРАН":"TROPHY WON"):cup.Finished?(GamePreferences.Russian?"ЗАВЕРШЁН":"COMPLETED"):cup.Eliminated?StoreText("ВЫБЫЛИ","ELIMINATED"):CanViewCup(cup)?(cup.Started?"IN PROGRESS":"AVAILABLE"):(GamePreferences.Russian?"ЗАКРЫТ":"LOCKED");
    string CupRequirement(CupTournament cup)
    {
        if(cup.Finished)return GamePreferences.Russian?"Результат в истории ниже":"Result in the history below";
        if(C.HasRelegationChoice)return StoreText("Сначала штраф или медиа-лига","First choose the fine or Media League");
        if(C.Pending!=null)return GamePreferences.Russian?"Завершите текущий матч":"Finish the current match";
        if(C.PlayedLeagueRounds<cup.OpensAfterRound)return GamePreferences.Russian?$"Откроется после тура {cup.OpensAfterRound} лиги":$"Play {cup.OpensAfterRound} league matches";
        return GamePreferences.Russian?"Сначала завершите текущий кубок":"Finish the active cup first";
    }
    static string CupRoundName(int round)=>round switch{1=>"Quarterfinal",2=>"Semifinal",3=>"Final",_=>"Cup match"};
    int Place=>C.Standings().FindIndex(r=>r.Team==0)+1;
    static int Opponent(ClubFixture f)=>f.Home==0?f.Away:f.Home;
    static string LeagueName(int division)=>ClubCareer.DivisionNames[Math.Clamp(division-1,0,4)];
    static string LeagueMark(int division)=>new[]{"III","II","I","N","★"}[Math.Clamp(division-1,0,4)];
    void PlayUpcoming(){if(C.Pending!=null)Game.ResumeMatch();else Game.PrepareCareer(C.DueCup!=null);}
    void InspectUpcoming(){if(Upcoming!=null){ShowOpponent(Opponent(Upcoming));OpponentTournament=C.TournamentFor(Upcoming);}}
    public int CrestReviewDivision=1;
    bool OpponentOpen;
    int OpponentSlot=1;
    CupTournament OpponentTournament;
    void ShowOpponent(int slot){if(slot<=0)return;OpponentTournament=null;OpponentSlot=slot;OpponentOpen=true;Game.SelectedClub=slot;}
    string SeasonFinishText=>C.Division==5 && Place==1?StoreText("Чемпион Премьер-лиги!","Premier League champion!"):Place<=2 && C.Division<5?StoreText("Выход в следующую лигу!","Promotion secured!"):Place==C.Standings().Count?StoreText("Вылет из лиги. Вернитесь сильнее в новом сезоне.","Relegated. Come back stronger next season."):StoreText("Впереди новый сезон.","A new season awaits.");
    void ClaimCareerReward(string id){if(C.ClaimCareerReward(id))Game.SaveCareer();}
    void ClaimMission(int round){if(C.ClaimMission(round))Game.SaveCareer();}
    string OpponentSlotStyle(Formation shape,int slot)
    {
        int formation=Array.IndexOf(Formation.All,shape);
        var five=new Point[]{new(50,88),new(16,69),new(39,69),new(61,69),new(84,69),new(38,50),new(62,50),new(22,31),new(50,31),new(78,31),new(50,12)};
        var point=formation==3?five[slot]:SquadLayouts[Math.Clamp(formation,0,3)][slot];
        return FormattableString.Invariant($"left:{point.X}%;top:{point.Y}%;");
    }
    PlayerCard Selected
    {
        get
        {
            var player=C.Cards.FirstOrDefault(p=>p.Id==SelectedCardId)??C.Card(SelectedSlot)??C.Cards.First();
            return Game.ClubPage=="Тренировки" && player.IsAcademyLoan?C.Cards.FirstOrDefault(p=>!p.IsAcademyLoan)??player:player;
        }
    }
    PlayerCard EquipmentCard=>Selected.Position=="ВР"?C.Cards.FirstOrDefault(p=>p.Position!="ВР")??Selected:Selected;
    int TeamRating=>C.PositionRating;
    void SelectSlot(int slot)
    {
        if(C.Card(slot)==null)return;SelectedSlot=slot;SelectedCardId=C.Lineup[slot];ProfileTab=0;DetailOpen=true;
    }
    void SelectReserve(int id){SelectedCardId=id;ProfileTab=0;DetailOpen=true;}
    static string SummaryIcon(string stat)=>"/ui-icons/attribute-line-v2-"+(stat switch{"PAC" or "SPD"=>"pace","SHO"=>"shooting","PAS" or "KIC"=>"passing","DRI"=>"dribbling","DEF"=>"defending","PHY"=>"physical","DIV" or "HAN" or "REF"=>"goalkeeping","POS"=>"positioning",_=>"physical"})+".svg";
    static string SummaryName(string stat)=>stat switch{"PAC"=>"PACE","SHO"=>"SHOOTING","PAS"=>"PASSING","DRI"=>"DRIBBLING","DEF"=>"DEFENDING","PHY"=>"PHYSICAL","DIV"=>"DIVING","HAN"=>"HANDLING","KIC"=>"KICKING","REF"=>"REFLEXES","SPD"=>"SPEED","POS"=>"POSITIONING",_=>stat};
    static string GroupIcon(string group)=>"/ui-icons/attribute-line-v2-"+(group switch{"Pace"=>"pace","Shooting"=>"shooting","Passing"=>"passing","Dribbling"=>"dribbling","Defending"=>"defending","Physical"=>"physical","Goalkeeping"=>"goalkeeping",_=>"positioning"})+".svg";
    // UI rows have room for cards; simulation positions are not screen layout coordinates.
    static Point[][] CachedLayouts;
    static int CachedLayoutRevision;
    static Point[][] SquadLayouts {get {if(CachedLayoutRevision!=20260929){CachedLayoutRevision=20260929;CachedLayouts=new Point[][]{
            new Point[]{new(50,87),new(16,62),new(39,62),new(61,62),new(84,62),new(16,37),new(39,37),new(61,37),new(84,37),new(38,12),new(62,12)},
            new Point[]{new(50,87),new(16,62),new(39,62),new(61,62),new(84,62),new(26,37),new(50,37),new(74,37),new(24,12),new(50,12),new(76,12)},
            new Point[]{new(50,87),new(25,62),new(50,62),new(75,62),new(12,37),new(31,37),new(50,37),new(69,37),new(88,37),new(38,12),new(62,12)},
            new Point[]{new(50,87),new(10,62),new(37,62),new(63,62),new(90,62),new(23.5f,49),new(76.5f,49),new(10,25),new(50,37),new(90,25),new(50,12)}
        };}return CachedLayouts;}}
    Point SquadSlotPoint(int slot)=>SquadLayouts[Math.Clamp(C.FormationIndex,0,3)][slot];
    string SquadSlotStyle(int slot){var p=SquadSlotPoint(slot);return FormattableString.Invariant($"left:{p.X}%;top:{p.Y}%;");}
    static string Stats(PlayerCard p)=>$"PAC {p.Pace} · SHO {p.Shooting} · PAS {p.Passing} · DEF {p.Defence} · STA {p.Endurance} · GK {p.Keeping} · AGG {p.Aggression} · COM {p.Composure}";
    static string SlotStyle(Point p)=>$"left: {(p.Y/68*100).ToString("0.##",CultureInfo.InvariantCulture)}%; top: {(94-p.X*1.15f).ToString("0.##",CultureInfo.InvariantCulture)}%;";
    string FixtureText(ClubFixture f)=>$"{C.TeamName(f.Home)}  {(f.Played?$"{f.HomeGoals}:{f.AwayGoals}":"—")}  {C.TeamName(f.Away)}";
    protected override int BuildHash()=>Game?.ClubOpen!=true?0:HashCode.Combine(HashCode.Combine(Game.ClubPage,Game.TutorialStep,(int)(Time.Now*(DragCardId>=0?30:10)),SelectedSlot,SelectedCardId,DetailOpen,TrainingGrade,TrainingItemId),HashCode.Combine(CatalogSearch,CatalogTier,CatalogSort,CatalogCountry,CatalogPosition,CatalogOwned,CatalogPage,SelectedCatalogKey),HashCode.Combine(BenchSearch,BenchFilter,DragCardId,DropSlot,ReviewAngle,ReviewClay))^HashCode.Combine(SelectedCatalogCopyId,OpenReport?.Key,ArchiveListOpen,ArchivePage)^HashCode.Combine(TrainingAnimation,SkillLibraryOpen,SkillLibraryGrade,GrantedUpgrade?.Skill,GamePreferences.Russian,CatalogSkills)^HashCode.Combine(StoreCupPacks,StoreCapsules,StoreInventory,StoreOfferIndex,BuyQuantity,C.Coins,C.CupTokens)^HashCode.Combine(ReviewLegendId,ProfileTab,SocerDeveloper.ShowNavigation,GamePreferences.Revision)^HashCode.Combine(TrainingPage,TrainingDiscardItemId,C.TrainingInventory.Count);
}