<script lang="ts">
	// Vertical step rail for multi-step wizards. Renders numbered steps with
	// a "molten" ember fill connecting completed steps — the forge control-
	// panel motif. Steps up to `maxReached` are clickable to jump back;
	// upcoming steps are inert. Collapses to a horizontal bar on narrow
	// viewports via CSS.
	interface WizardStep {
		label: string;
	}

	interface Props {
		steps: WizardStep[];
		/** 1-based index of the active step. */
		current: number;
		/** 1-based index of the furthest step the user may navigate to. */
		maxReached: number;
		onselect: (step: number) => void;
	}

	let { steps, current, maxReached, onselect }: Props = $props();

	function stepState(index1: number): 'done' | 'active' | 'upcoming' {
		if (index1 < current) return 'done';
		if (index1 === current) return 'active';
		return 'upcoming';
	}

	function pad(n: number): string {
		return String(n).padStart(2, '0');
	}

	// Up/Down arrows move focus among the reachable (enabled) step buttons
	// so the rail reads as one grouped control to keyboard users.
	function handleKeydown(e: KeyboardEvent): void {
		if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;
		const list = (e.currentTarget as HTMLElement).closest('.rail-list');
		if (!list) return;
		const btns = Array.from(list.querySelectorAll<HTMLButtonElement>('button:not([disabled])'));
		const idx = btns.indexOf(e.currentTarget as HTMLButtonElement);
		if (idx === -1) return;
		e.preventDefault();
		const target =
			e.key === 'ArrowDown' ? Math.min(idx + 1, btns.length - 1) : Math.max(idx - 1, 0);
		btns[target]?.focus();
	}
</script>

<nav class="rail" aria-label="Progress">
	<ol class="rail-list">
		{#each steps as step, i (i)}
			{@const num = i + 1}
			{@const st = stepState(num)}
			{@const reachable = num <= maxReached && num !== current}
			<li class="rail-item rail-{st}">
				<button
					type="button"
					class="rail-btn"
					disabled={!reachable}
					aria-current={st === 'active' ? 'step' : undefined}
					onclick={() => reachable && onselect(num)}
					onkeydown={handleKeydown}
				>
					<span class="rail-marker" aria-hidden="true">
						{#if st === 'done'}
							<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5l3.5 3.5L13 4" /></svg>
						{:else}
							{pad(num)}
						{/if}
					</span>
					<span class="rail-label">{step.label}</span>
				</button>
			</li>
		{/each}
	</ol>
</nav>

<style>
	.rail {
		flex-shrink: 0;
	}

	.rail-list {
		list-style: none;
		margin: 0;
		padding: 0;
		display: flex;
		flex-direction: column;
		gap: 0;
	}

	.rail-item {
		position: relative;
	}

	/* Connector line between markers. Drawn from this marker's centre
	   upward to the previous one; ember-filled once the step is reached. */
	.rail-item:not(:first-child)::before {
		content: '';
		position: absolute;
		left: calc(0.875rem - 1px);
		top: calc(-0.5rem);
		height: 0.5rem;
		width: 2px;
		background: var(--border-primary);
		transition: background var(--transition-slow);
	}

	.rail-done:not(:first-child)::before,
	.rail-active:not(:first-child)::before {
		background: var(--forge-ember);
	}

	.rail-btn {
		display: flex;
		align-items: center;
		gap: var(--space-3);
		width: 100%;
		padding: var(--space-2) var(--space-2);
		background: transparent;
		border: none;
		border-radius: var(--radius-md);
		cursor: pointer;
		text-align: left;
		color: var(--text-tertiary);
		transition: color var(--transition-fast), background var(--transition-fast);
	}

	.rail-btn:not(:disabled):hover {
		background: var(--surface-card-hover);
		color: var(--text-secondary);
	}

	.rail-btn:disabled {
		cursor: default;
	}

	.rail-marker {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		flex-shrink: 0;
		width: 1.75rem;
		height: 1.75rem;
		border-radius: var(--radius-full);
		border: 2px solid var(--border-primary);
		background: var(--surface-card);
		font-family: var(--font-family-mono);
		font-size: var(--text-xs);
		font-weight: var(--weight-semibold);
		color: var(--text-tertiary);
		transition: all var(--transition-fast);
	}

	.rail-done .rail-marker {
		border-color: var(--forge-ember);
		background: var(--forge-ember);
		color: #fff;
	}

	.rail-active .rail-marker {
		border-color: var(--forge-ember);
		color: var(--forge-ember);
		box-shadow: 0 0 0 4px color-mix(in srgb, var(--forge-ember) 18%, transparent);
	}

	.rail-label {
		font-size: var(--text-sm);
		font-weight: var(--weight-medium);
		line-height: var(--leading-tight);
	}

	.rail-active .rail-label {
		color: var(--text-primary);
		font-weight: var(--weight-semibold);
	}

	.rail-done .rail-label {
		color: var(--text-secondary);
	}

	/* Horizontal rail on narrow screens: markers in a row, labels hidden. */
	@media (max-width: 820px) {
		.rail-list {
			flex-direction: row;
			gap: 0;
			justify-content: space-between;
		}
		.rail-item {
			flex: 1;
			display: flex;
			justify-content: center;
		}
		.rail-item:not(:first-child)::before {
			left: auto;
			right: 50%;
			top: calc(0.875rem - 1px);
			height: 2px;
			width: 100%;
		}
		.rail-btn {
			flex-direction: column;
			gap: var(--space-1);
			width: auto;
			z-index: 1;
		}
		.rail-label {
			display: none;
		}
	}
</style>
