diff --git a/frontend/src/components/RankBonusModal.svelte b/frontend/src/components/RankBonusModal.svelte
new file mode 100644
index 0000000..33a6ad2
--- /dev/null
+++ b/frontend/src/components/RankBonusModal.svelte
@@ -0,0 +1,104 @@
+
+
+{#if me.needs_rank_3_bonus}
+
+
+
⭐ Your Story is Complete!
+
+ You completed your final Personal Objective and earned your rest. Choose a
+ crewmate to carry on stronger — they gain 1 Rank.
+
+ {#if error}
+
{error}
+ {/if}
+ {#if eligible.length}
+
+ {#each eligible as p (p.id)}
+
+ {/each}
+
+ {:else}
+
No crewmate is eligible to receive the Rank right now.
+
+ {/if}
+
+
+{/if}
+
+
diff --git a/frontend/src/components/scene/ObstacleItem.svelte b/frontend/src/components/scene/ObstacleItem.svelte
new file mode 100644
index 0000000..fae2514
--- /dev/null
+++ b/frontend/src/components/scene/ObstacleItem.svelte
@@ -0,0 +1,116 @@
+
+
+ { if (!is_completed) e.preventDefault(); }}
+ on:dragenter={(e) => { if (!is_completed) e.currentTarget.classList.add("drag-over"); }}
+ on:dragleave={(e) => { if (!is_completed) e.currentTarget.classList.remove("drag-over"); }}
+ on:drop={(e) => {
+ if (is_completed) return;
+ e.preventDefault();
+ e.currentTarget.classList.remove("drag-over");
+ const cardCode = e.dataTransfer.getData('text/plain');
+ if (cardCode) {
+ if (isJoker(cardCode)) playJoker(cardCode);
+ else playCard(cardCode);
+ }
+ }}>
+ {#if error}
+
{error}
+ {/if}
+
+
+ Original card
+
+
+
{obs.title} {#if in_challenge && !embedded}⚔️ In Challenge{/if}
+
+ {is_red ? 'Red' : 'Black'} obstacle · match to draw
+
+
{obs.description}
+
+
+
+
+ Current Difficulty
+
+ {#if is_face_active}
+ {challengedRank !== null ? `${challengedRank} (Rat's Rank)` : "Challenged Rat's Rank"}
+ {:else}
+ {obs.current_value}
+ {/if}
+
+
+
+
+
+ Successes
+ {success_count} / {state.players.length}
+
+
+
+
+
Card History (Column)
+
+
+ {#each column_cards as pc}
+
+ {/each}
+
+
+
+ {#if is_completed && state.player.role === 'deep'}
+
+
+
+ {/if}
+
diff --git a/frontend/src/lib/tooltip.js b/frontend/src/lib/tooltip.js
new file mode 100644
index 0000000..9d09846
--- /dev/null
+++ b/frontend/src/lib/tooltip.js
@@ -0,0 +1,84 @@
+// A styled hover/focus tooltip that replaces the native `title` attribute.
+//
+// use:tooltip={"plain text"} -> rendered as text
+// use:tooltip={{ html: "