@props([
    'name' => 'code',
    'length' => 6,
    'label' => null,
])
{{-- Segmented one-time-code input. Alpine keeps the visible segments; a hidden
     field carries the joined value for the native form POST — or, inside a
     Livewire form, for wire:model. wire:model needs both the attribute (so
     Livewire's directive scan finds it — hence spreading $attributes here) and
     a real "input" event: Alpine's :value binding only ever writes the DOM
     property, which fires nothing on its own. --}}
<div
    x-data="otpInput({ length: {{ (int) $length }} })"
    class="flex gap-2"
    role="group"
    @if ($label) aria-label="{{ $label }}" @endif
>
    <input type="hidden" name="{{ $name }}" :value="value" x-effect="$el.dispatchEvent(new Event('input', { bubbles: true }))" {{ $attributes }}>
    <template x-for="(digit, i) in digits" :key="i">
        <input
            type="text"
            inputmode="numeric"
            autocomplete="one-time-code"
            maxlength="1"
            class="size-12 rounded border border-line bg-surface text-center font-mono text-lg text-ink"
            :aria-label="`{{ $label ?? __('auth.otp_digit') }} ${i + 1}`"
            x-model="digits[i]"
            x-ref="cell"
            @input="onInput(i, $event)"
            @keydown.backspace="onBackspace(i, $event)"
            @paste.prevent="onPaste($event)"
        >
    </template>
</div>
