{#if error}
{error}
{/if} {#each openChallenges as ch} {@const chObstacleIds = JSON.parse(ch.obstacle_ids || '[]')}

{#if ch.challenge_type === 'pvp'} ⚔️ Duel: {playerName(ch.challenger_player_id)} vs {playerName(ch.target_player_id)} {:else} ⚔️ The Deep challenges {playerName(ch.target_player_id)}! {/if}

{#if state.player.role === 'deep' && ch.challenge_type === 'deep'}
{/if}
{#if ch.stakes_success}

✅ On success: {ch.stakes_success}

{/if} {#if ch.stakes_failure}

❌ On failure: {ch.stakes_failure}

{/if} {#if ch.stakes && !ch.stakes_success && !ch.stakes_failure}

Stakes: {ch.stakes}

{/if} {#if ch.challenge_type === 'pvp'}

Temporary Obstacle: {getCardDisplay(ch.temp_card)} — {playerName(ch.acting_player_id)} must answer it!

{:else}

{state.obstacles.filter(o => chObstacleIds.includes(o.id)).length > 1 ? 'Other Pi-Rats may assist with one card each. Only the attempting Pi-Rat draws replacements after resolution.' : 'Only the attempting Pi-Rat can play against this single Obstacle. Matching colors earn a replacement after resolution.'}

{#each chObstacleIds as oid} {@const obs = state.obstacles.find(o => o.id === oid)} {#if obs} {:else}

An applied Obstacle was discarded.

{/if} {/each}
{/if} {#if ch.tax_state === 'requested'} {#if myTaxRequest && myTaxRequest.id === ch.id}

{playerName(ch.target_player_id)} calls a {ch.tax_type === 'gat' ? 'Gat' : 'Name'} Tax on you: take this Challenge for them!

Accept: you get one random card from their hand and attempt the Challenge. Refuse: you hand over your {ch.tax_type === 'gat' ? 'Gat' : 'Name'} — they keep it if they succeed!

{:else}

⏳ Waiting for {playerName(ch.tax_target_id)} to answer the {ch.tax_type === 'gat' ? 'Gat' : 'Name'} Tax...

{/if} {/if} {#if ch.challenge_type === 'deep' && ch.acting_player_id === state.player.id && !ch.tax_state && !state.player.tax_banned && taxType(state.player) && eligibleTaxTargets().length > 0}
No {taxType(state.player)}? Make it someone else's problem:
{/if} {#if myPvpDefense && myPvpDefense.id === ch.id}

Defend yourself! Match the Obstacle’s color to draw a replacement, even if you lose:

{#each hand.filter(c => !isJoker(c)) as card} {/each}
{/if}
{/each} {#each completedDuels as ch (ch.id)}

⚔️ Duel: {playerName(ch.challenger_player_id)} vs {playerName(ch.target_player_id)}

{ch.status === 'succeeded' ? '✓' : '✕'} {playerName(ch.acting_player_id)} {ch.status === 'succeeded' ? 'won the defense' : 'lost the defense'}. {playerName(ch.status === 'succeeded' ? ch.acting_player_id : ch.challenger_player_id)} wins the duel.

Temporary Obstacle: {getCardDisplay(ch.temp_card)}

{#each JSON.parse(ch.plays || '[]') as play}

Defense: {getCardDisplay(play.card)}. {play.details}

{/each}
{/each} {#if isDeep && openChallenges.length === 0}
{#if showCreate}

Establish the stakes, pick a Pi-Rat, and apply one or more Obstacles. They play one card per Obstacle — beating one passes; each failure breeds a complication.

{#each state.obstacles as obs} {@const taken = challengedObstacleIds.has(obs.id)} {/each}
{/if}

End the scene once every Pi-Rat has faced a Challenge and had a chance at an Objective, or the Obstacle List is empty.

{/if}