/**
------------------------------------------------------------------------------
ONE TIME CODE INPUT (2FA / TOTP)

A single real <input> painted as a row of separate boxes. Everything the
browser already does well - pasting, SMS/authenticator autofill, caret
movement, undo, password managers, screen reader labelling - keeps working,
because there is still only one field; the boxes are decoration mirrored from
its value by otp-input.js.

Without javascript the input simply stays a plain .form-control.
------------------------------------------------------------------------------
*/

.otp-field {
    --otp-gap: 6px;
    --otp-cell-width: 36px;
    --otp-cell-height: 44px;
    --otp-border: #ccc;
    --otp-border-filled: #8c8c8c;
    --otp-accent: #d42824;
    --otp-text: #333;

    max-width: 24em;
    line-height: normal;
}

.otp-field .otp-boxes {
    position: relative;
}

/**
------------------------------
THE BOXES
------------------------------
*/

.otp-field .otp-cells {
    display: flex;
    gap: var(--otp-gap);
}

.otp-field .otp-cell {
    position: relative;
    flex: 1 1 var(--otp-cell-width);
    min-width: 0;
    max-width: var(--otp-cell-width);
    height: var(--otp-cell-height);
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #fff;
    border: 1px solid var(--otp-border);
    border-radius: 2px;
    font-family: Ubuntu, sans-serif;
    font-size: 18px;
    font-weight: 500;
    color: var(--otp-text);
    transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}

/* a middle gap makes a six digit code easier to read back from the app */
.otp-field .otp-cell.otp-cell-group-end {
    margin-right: calc(var(--otp-gap) * 1.25);
}

.otp-field .otp-cell.is-filled {
    border-color: var(--otp-border-filled);
}

.otp-field .otp-char {
    display: block;
    line-height: 1;
}

/**
------------------------------
FOCUS AND CARET
------------------------------
*/

.otp-field.is-focused .otp-cell.is-active,
.otp-field.is-focused .otp-cell.is-selected {
    border-color: var(--otp-accent);
    box-shadow: 0 0 0 2px rgba(212, 40, 36, .18);
}

.otp-field.is-focused .otp-cell.is-selected {
    background-color: rgba(212, 40, 36, .06);
}

.otp-field .otp-caret {
    display: none;
    position: absolute;
    width: 2px;
    height: 20px;
    background-color: var(--otp-accent);
    border-radius: 1px;
}

.otp-field.is-focused .otp-cell.is-active.is-empty .otp-caret {
    display: block;
    animation: otp-caret-blink 1.1s steps(1, end) infinite;
}

@keyframes otp-caret-blink {
    0%, 49%   { opacity: 1; }
    50%, 100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .otp-field .otp-cell { transition: none; }
    .otp-field .otp-caret { animation: none; }
}

/**
------------------------------
THE REAL INPUT

Sits on top of the boxes so it keeps every native behaviour, but paints
nothing of its own. Font size stays at 16px so iOS does not zoom on focus.
------------------------------
*/

.otp-field.otp-field-code .otp-native {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    z-index: 2;
    background-color: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    outline: none;
    color: transparent;
    caret-color: transparent;
    text-align: center;
    font-size: 16px !important;
    -webkit-text-fill-color: transparent;
    -webkit-tap-highlight-color: transparent;
}

.otp-field.otp-field-code .otp-native::selection {
    background-color: transparent;
    color: transparent;
}

.otp-field.otp-field-code .otp-native::-moz-selection {
    background-color: transparent;
    color: transparent;
}

/**
------------------------------
ERROR STATE
------------------------------
*/

.otp-field.is-invalid .otp-cell {
    border-color: var(--otp-accent);
    background-color: rgba(212, 40, 36, .05);
}

.otp-field.is-invalid .otp-native.form-control {
    border-color: var(--otp-accent);
}

/**
------------------------------
HINT AND RECOVERY CODE TOGGLE
------------------------------
*/

.otp-field .otp-hint {
    margin-top: 8px;
    font-size: 12px;
    line-height: 1.4;
    color: #777;
}

.otp-field .otp-toggle {
    display: inline-block;
    margin-top: 6px;
    font-size: 12px;
    cursor: pointer;
}

/**
------------------------------
FREE TEXT MODE (recovery codes)

The boxes step aside and the very same input goes back to being an ordinary
.form-control, so a 20 character recovery code can be typed or pasted.
------------------------------
*/

.otp-field.otp-field-text .otp-cells {
    display: none;
}

/* the hint talks about the authenticator app, which is not what is being typed here */
.otp-field.otp-field-text .otp-hint {
    display: none;
}

.otp-field.otp-field-text .otp-native {
    font-family: Consolas, Menlo, Monaco, monospace;
    font-size: 16px;
    height: 40px;
    letter-spacing: .06em;
}

/**
------------------------------
SMALL SCREENS
------------------------------
*/

@media all and (max-width: 480px) {
    .otp-field {
        --otp-gap: 5px;
        --otp-cell-height: 39px;
    }

    .otp-field .otp-cell {
        font-size: 16px;
    }

    .otp-field .otp-caret {
        height: 17px;
    }
}

@media all and (max-width: 360px) {
    .otp-field {
        --otp-gap: 3px;
        --otp-cell-height: 35px;
    }

    .otp-field .otp-cell {
        font-size: 14px;
    }

    .otp-field .otp-cell.otp-cell-group-end {
        margin-right: var(--otp-gap);
    }

    .otp-field .otp-caret {
        height: 15px;
    }
}

/**
------------------------------
THE ROW IT SITS IN
------------------------------

dl.zend_form floats a narrow label column beside a narrow field column. A row of
boxes does not sit well there: the label belongs above the field, and both cells
want the whole width. Every consumer used to carry its own copy of these four
rules in an inline <style>, keyed on that form's generated element ids - four
near identical blocks. They are here once now, on classes otp-input.js adds to
the dt/dd pair when a caller passes stackRow (and submit, for the button's row).

Classes rather than ids, which is enough: the rules being overridden are
`.zend_form dt` and `.zend_form dd` in global.css, and two classes plus two type
selectors outrank one class plus one type.

The two width declarations are !important, which the rest of this file manages
without. A host form may size its own rows by id - login.phtml carries
`#loginFrm dt, #login2faFrm dt { width: 9em }` and a matching 22em rule for its
dd - and an id outranks any number of classes, so without it the boxes get
squeezed into 22em and the label cell stays 9em wide. The 24em is what the old
inline blocks set for exactly that reason; it is not redundant with .otp-field's
own cap, it is what stops the cell capping the field below it.
*/

dl.zend_form dt.otp-stack-label {
    clear: both;
    width: 100% !important;
    max-width: none !important;
    margin-left: 0;
}

dl.zend_form dd.otp-stack {
    clear: both;
    width: 100% !important;
    max-width: 24em !important;
    margin-left: 0;
    margin-bottom: 15px;
}

/* the submit sits under the boxes, so its label cell is dead weight */
dl.zend_form dt.otp-stack-submit-label {
    display: none;
}

dl.zend_form dd.otp-stack-submit {
    clear: both;
    margin-left: 0;
}
