diff --git a/README.md b/README.md
index 4a7c6a6d..73f2ddee 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,10 @@ Use **Bribes** beneath the table to pay a non-allied faction. The recipient's
share becomes spendable at the next Mentat Pause; the panel shows your own
incoming bribes and the current payment limit. See [bribe controls](docs/BRIBE_CONTROLS.md).
+At a Nexus, an unanswered alliance offer names its recipient and offers
+**Withdraw your alliance offer**. Formed alliances keep the separate **Break
+alliance** action. See [Nexus offers](docs/NEXUS_OFFERS.md).
+
The table header offers optional **Sound effects**, with mute, volume and a test
sample. Short cues mark phase changes and automatic action notices. Sound starts
off; preferences stay in your browser. See [table sounds](docs/TABLE_SOUNDS.md)
diff --git a/app/globals.css b/app/globals.css
index dda7e4db..39f9b56e 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1949,3 +1949,6 @@ footer {
.bribe-fields label { display: grid; gap: .35rem; flex: 1 1 12rem; min-width: 0; }
.bribe-fields select, .bribe-fields input { min-height: 44px; width: 100%; min-width: 0; font-size: 1rem; }
.bribe-fields button { font-size: 1rem; min-height: 44px; max-width: 100%; height: auto; white-space: normal; overflow-wrap: anywhere; }
+
+.nexus-offer .notice, .nexus-offer .game-action { font-size: 1rem; }
+.nexus-offer .game-action { min-height: 44px; height: auto; max-width: 100%; white-space: normal; }
diff --git a/components/game-table.tsx b/components/game-table.tsx
index f5de4015..29e00c7e 100644
--- a/components/game-table.tsx
+++ b/components/game-table.tsx
@@ -210,6 +210,8 @@ export function GameTable({
exitDisabled?: boolean;
}) {
const me = g.players.find((p) => p.id === g.me)!;
+ const outgoingAlliance = g.allianceOffers[me.id];
+ const outgoingAllianceName = g.players.find((p) => p.id === outgoingAlliance)?.name;
const shipmentAvailable = nexusGuildShipmentAvailable(g);
const movementAvailable = nexusGuildMovementAvailable(g);
const guildCunning = nexusGuildCunningActive(g);
@@ -3392,6 +3394,15 @@ export function GameTable({
A sandworm has opened a Nexus. Alliances may change now.
+ {outgoingAlliance && !me.ally && (
+
+
+ Your alliance offer is to {outgoingAllianceName ?? 'a player no longer seated'}.
+ You remain unallied until both players agree.
+
+ {actionButton('Withdraw your alliance offer', { type: 'alliance' })}
+
+ )}