diff --git a/README.md b/README.md
index 3eba50ab..3dbecf3f 100644
--- a/README.md
+++ b/README.md
@@ -189,6 +189,19 @@ Full hands and same-card redraw from an exhausted deck are supported.
Harkonnen buyers and special sale origins remain guarded; see
[verified source, privacy and runtime boundaries](docs/NEXUS_IXIAN_REPLACEMENT_RULES.md).
+For local **Ixian Nexus Betrayal**, use
+`node --import tsx tools/start-prototype.ts --profile ixian-betrayal`
+on a fresh ready Basic/Advanced lobby with native Ixians, otherwise classic
+factions or Tleilaxu, the forty-seven-card Ix Treachery Deck and Nexus alone.
+Exact-version/private-backup safeguards apply; no existing-game retrofit or
+public start is enabled. Native alliance-qualified Nexus rights still apply.
+Original Karama counters resolve first; neutral rival acknowledgements then
+offer **Pass** or privately eligible **Use Ixian Nexus** before the original
+Bidding inspection/draw or Advanced Technology exchange. Use spends one
+physical Nexus and prevents only that attempt; all-pass keeps its native
+effect and continuation. See the
+[bounded verified runtime](docs/NEXUS_CARD_RUNTIME.md#bounded-ixian-betrayal-local-runtime--1-october-2026).
+
Above the board, **Treachery draw pile** and **Spice draw pile** show live card
counts separately from hands, auction cards and discards. See
[draw-pile counts](docs/DRAW_PILES.md).
diff --git a/components/game-table.tsx b/components/game-table.tsx
index 4dbee962..757d0fd7 100644
--- a/components/game-table.tsx
+++ b/components/game-table.tsx
@@ -82,6 +82,7 @@ import { ChoamKull } from './choam-kull';
import { NexusRicheseBetrayal } from './nexus-richese-betrayal';
import { NexusGuildBetrayal } from './nexus-guild-betrayal';
import { NexusIxianReplacement } from './nexus-ixian-replacement';
+import { NexusIxianBetrayal } from './nexus-ixian-betrayal';
import { OrnithopterMovement } from './ornithopter-movement';
import { DiscoveryOrnithopterMovement } from './discovery-flight-movement';
import { PlanetologistMovement } from './planetologist-movement';
@@ -306,8 +307,11 @@ export function GameTable({
);
const reactionBusy =
transportBusy || !!g.roomControl?.paused || !!g.roomControl?.closed || !!me.autopilot;
- const busy = reactionBusy || g.automaticContinuationPending || !!g.semutaReaction || !!g.kullReaction || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction || !!g.nexusIxianReplacement;
- const reactionOwnsControls = !!g.kullReaction || !!g.kullCounterEvent || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction || !!g.nexusIxianReplacement;
+ const ixianBetrayalOwnsControls = !!g.nexusIxianBetrayalReaction &&
+ !g.response && !g.decision && !g.truthtrance && !g.phaseOpening &&
+ !g.automaticContinuationPending && !g.nexusCards?.waiting.length && !g.nexusTraitors?.pending;
+ const busy = reactionBusy || g.automaticContinuationPending || !!g.semutaReaction || !!g.kullReaction || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction || !!g.nexusIxianReplacement || ixianBetrayalOwnsControls;
+ const reactionOwnsControls = !!g.kullReaction || !!g.kullCounterEvent || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction || !!g.nexusIxianReplacement || ixianBetrayalOwnsControls;
const canActivateKarama = (card: Card) =>
!g.karamaBlocked && canUseAsKaramaRole(g, me, card);
const traitorBattle = g.battle;
@@ -784,6 +788,15 @@ export function GameTable({
!botGroundMoveAllowed(g, me, key, boardLocation(selected, sector), 0),
);
const act = (a: Action) => {
+ // Control of one's own seat is independent of every gameplay response.
+ if (a.type === 'setAutopilot') { void send(a); return; }
+ const ixianReaction = g.nexusIxianBetrayalReaction;
+ if (ixianReaction && ixianBetrayalOwnsControls) {
+ if (reactionBusy || g.status !== 'playing' || !ixianReaction.canPass || ixianReaction.hasPassed ||
+ (a.type !== 'nexusIxianBetrayalPass' && a.type !== 'nexusIxianBetrayalUse') ||
+ a.event !== ixianReaction.event ||
+ (a.type === 'nexusIxianBetrayalUse' && (!ixianReaction.canUse || ixianReaction.blocked))) return;
+ }
const guildReaction = g.guildBetrayalReaction;
if (guildReaction) {
if (reactionBusy || g.status !== 'playing' || !guildReaction.canPass || guildReaction.hasPassed ||
@@ -1029,6 +1042,8 @@ export function GameTable({
faction(g.players.find((p) => p.id === id)!.faction).name,
)
.join(' + ') || 'No winner'
+ : ixianBetrayalOwnsControls
+ ? 'Native Ixian advantage acknowledgement'
: g.guildBetrayalReaction
? 'Shipment payment acknowledgement'
: g.richeseBetrayalReaction
@@ -1093,6 +1108,15 @@ export function GameTable({
Preview rules and limits
)}
+ {g.nexusIxianBetrayalPreview && (
+
+ Ixian Nexus Betrayal development preview · native Ixian Bidding extra-card
+ inspection/draw and Advanced Technology exchange prevention. Native Ixians,
+ permitted classic/Tleilaxu seats, physical Ixian Treachery and Nexus only.
+ Native Karama responses finish first. Not complete Ixian or certified Nexus rules.{' '}
+ Preview rules and limits
+
+ )}
{g.status !== 'lobby' && (