/* otp-cells — six-cell 2FA code entry (otp-cells.ejs, behaviour in otp-cells.js).
   The value itself stays in the hidden input; the cells are only how it is typed. */
.otp-cells { display: flex; justify-content: center; align-items: center; gap: 8px; margin-bottom: 1rem; }
.otp-cells .otp-cell { width: 46px; height: 56px; padding: 0; border: 1.5px solid var(--theme-line); border-radius: 10px; background: var(--theme-tint); color: var(--theme-ink); text-align: center; font-size: 1.5rem; font-weight: 500; caret-color: var(--theme-primary); }
.otp-cells .otp-cell.is-filled { border-color: var(--theme-line-strong); background: #fff; }
.otp-cells .otp-cell:focus { outline: none; border-color: var(--theme-primary); background: #fff; box-shadow: 0 0 0 .25rem rgba(var(--theme-primary-rgb), .15); }
.otp-cells .otp-sep { flex: none; width: 10px; height: 2px; border-radius: 1px; background: var(--theme-line-strong); }
.otp-cells-label { display: block; text-align: center; color: #6c757d; margin-bottom: .5rem; }
/* A rejected code: red cells + a short shake (OtpCells.error), then they clear for a retry. */
.otp-cells .otp-cell.is-error { border-color: #dc3545; background: #fdf2f4; }
.otp-cells.otp-shake { animation: otp-cells-shake .42s cubic-bezier(.36, .07, .19, .97) both; }
@keyframes otp-cells-shake { 10%, 90% { transform: translateX(-1px); } 20%, 80% { transform: translateX(3px); } 30%, 50%, 70% { transform: translateX(-5px); } 40%, 60% { transform: translateX(5px); } }

@media (prefers-reduced-motion: reduce) { .otp-cells.otp-shake { animation: none; } }
@media (max-width: 400px) {
    .otp-cells { gap: 6px; }
    .otp-cells .otp-cell { width: 40px; height: 50px; font-size: 1.25rem; }
}
@media (max-width: 330px) {
    .otp-cells { gap: 4px; }
    .otp-cells .otp-cell { width: 34px; height: 46px; }
}
