-
+
diff --git a/src/components/game/tabs/SpireCombatPage/SpireHeader.tsx b/src/components/game/tabs/SpireCombatPage/SpireHeader.tsx
index a1cc533..7c2d194 100644
--- a/src/components/game/tabs/SpireCombatPage/SpireHeader.tsx
+++ b/src/components/game/tabs/SpireCombatPage/SpireHeader.tsx
@@ -5,7 +5,7 @@ import { useShallow } from 'zustand/react/shallow';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress';
-import { Mountain, ArrowUp, ArrowDown, LogOut } from 'lucide-react';
+import { Mountain, ArrowUp, ArrowDown, LogOut, ChevronDown } from 'lucide-react';
import { getGuardianForFloor, isGuardianFloor } from '@/lib/game/data/guardian-encounters';
import { DebugName } from '@/components/game/debug/debug-context';
@@ -34,11 +34,16 @@ export function SpireHeader({
}: SpireHeaderProps) {
const maxFloorReached = useCombatStore((s) => s.maxFloorReached);
const insight = usePrestigeStore((s) => s.insight);
+ // ─── Spec: read climbDirection and isDescentComplete ─────────────────────
+ const climbDirection = useCombatStore((s) => s.climbDirection);
+ const isDescentComplete = useCombatStore((s) => s.isDescentComplete);
+ const enterDescentMode = useCombatStore((s) => s.enterDescentMode);
const guardian = getGuardianForFloor(currentFloor);
const isGuardian = isGuardianFloor(currentFloor);
const hpPercent = floorMaxHP > 0 ? (floorHP / floorMaxHP) * 100 : 100;
const roomProgress = totalRooms > 0 ? ((roomsCleared) / totalRooms) * 100 : 0;
+ const isAscending = climbDirection === 'up';
return (
@@ -59,27 +64,47 @@ export function SpireHeader({
-
-
- {currentFloor === 1 && (
+ {/* ── Spec §4.5: "Descend" button available at any point during ascent ── */}
+ {isAscending && (
+
+ )}
+
+ {/* Legacy climb buttons (kept for non-spire-mode compatibility) */}
+ {!climbDirection && (
+ <>
+
+
+ >
+ )}
+
+ {/* ── Spec §4.9: "Exit Spire" only visible when isDescentComplete ── */}
+ {isDescentComplete && (