/*
 * Nebula Passkey, storefront stylesheet.
 *
 * Named `module.css` because that path is a contract: NFT's ModuleAsset\Registry collects
 * `view/frontend/web/css/module.css` from every enabled module and emits a <link> for it. That
 * registry lives in nft-core and fires only when NFT renders the head, which is why the layout
 * files still declare this file with <css> as well. The two routes are not redundant, they cover
 * different themes: under NFT the base layout reset strips the <css> from the account handles and
 * the registry supplies the file instead; on Luma, Hyva or a bespoke theme there is no reset, no
 * registry, and the <css> is the only route. One file, one URL, reached two ways.
 *
 * The exception is `customer_account_login.xml`, which keeps its excludeFromResets entry for an
 * unrelated reason, so under NFT that one page is linked by both routes. Same URL, so the browser
 * fetches it once.
 *
 * Theme neutral on purpose, and that is a different rule from the admin side of this module.
 *
 * The admin templates consume the Nebula theme's `--nebula-*` tokens and its component vocabulary,
 * because a Nebula admin package renders inside the Nebula admin theme and may depend on it (D37).
 * There is no equivalent guarantee on the storefront: this module requires the admin theme and says
 * nothing about which frontend theme a merchant runs. This install is Luma; the next may be Hyva or
 * a bespoke child theme.
 *
 * So the storefront markup leans on `.action.primary`, `.action.secondary` and `.message` where a
 * theme is overwhelmingly likely to have styled them (Luma and Hyva both do, and they are Magento's
 * own class names rather than any theme's invention), and this file supplies only the layout that no
 * theme can be expected to have an opinion about. Custom properties with fallbacks, so a theme that
 * defines them wins and a theme that does not still renders.
 */

.nebula-passkey-account {
    --nebula-pk-border: var(--color-gray-light, #d1d1d1);
    --nebula-pk-muted: var(--color-text-muted, #575757);
    --nebula-pk-radius: 3px;
}

.nebula-passkey-account__intro {
    margin-bottom: 1.5rem;
}

.nebula-passkey-account__toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.nebula-passkey-account__empty {
    padding: 2.5rem 1rem;
    border: 2px dashed var(--nebula-pk-border);
    border-radius: var(--nebula-pk-radius);
    text-align: center;
    color: var(--nebula-pk-muted);
}

.nebula-passkey-account__table {
    width: 100%;
    border-collapse: collapse;
}

.nebula-passkey-account__table th,
.nebula-passkey-account__table td {
    padding: 0.75rem 0.5rem;
    text-align: left;
    border-bottom: 1px solid var(--nebula-pk-border);
    vertical-align: middle;
}

.nebula-passkey-account__table th {
    font-weight: 600;
}

.nebula-passkey-account__meta {
    color: var(--nebula-pk-muted);
    white-space: nowrap;
}

.nebula-passkey-account__row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: flex-end;
}

/* A link-weight control, so a row of them does not compete with the page's Add button. */
.nebula-passkey-account__action {
    border: 0;
    padding: 0;
    background: none;
    font: inherit;
    cursor: pointer;
    text-decoration: underline;
}

.nebula-passkey-account__rename-input {
    width: 100%;
    max-width: 20rem;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--nebula-pk-border);
    border-radius: var(--nebula-pk-radius);
    font: inherit;
}

/* The table drops to stacked rows on a phone, since four columns and two actions do not fit. */
@media (max-width: 640px) {
    .nebula-passkey-account__table thead {
        display: none;
    }

    .nebula-passkey-account__table tr {
        display: block;
        padding: 0.75rem 0;
        border-bottom: 1px solid var(--nebula-pk-border);
    }

    .nebula-passkey-account__table td {
        display: block;
        border: 0;
        padding: 0.15rem 0;
    }

    .nebula-passkey-account__row-actions {
        justify-content: flex-start;
        margin-top: 0.5rem;
    }
}

/* --------------------------------------------------------------------------- the sign-in form */

/*
 * These rules go with `customer/login-form.phtml`, which this module owns. That file explains why
 * it exists; this explains the one idea the layout rests on.
 *
 * ONE ROW, ONE GAP. The actions row holds Sign In, the word "or" and the passkey button, and the
 * space either side of "or" has to be equal. Two margins that happen to match are not equal, they
 * are equal until somebody edits one; a single `gap` on their shared parent is equal by
 * construction. That is why the passkey block is `display: contents` — its box is removed so its
 * divider and its button are items of the same row as Sign In rather than a nested pair with
 * spacing of their own.
 */

.nebula-login__field-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.25rem 1rem;
}

/*
 * The required-fields note. It sits with the fields it is about, right-aligned opposite Show
 * Password, and it is a real element rather than core's `content: attr(data-hasrequired)` — a
 * pseudo-element cannot be placed anywhere except last, which is how it kept ending up beside the
 * submit button.
 */
.nebula-login__required {
    margin: 0;
    color: var(--color-error, #e02b27);
    font-size: 0.9em;
}

.nebula-login__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    margin-top: 1.5rem;
}

/* Whatever the theme spaces its buttons with, the row's gap is the only spacing here. */
.nebula-login__actions > .action,
.nebula-login__actions [data-passkey-submit] {
    margin: 0;
}

/* Left aligned and on its own line: it is a way out of a problem, not a third way in. */
.nebula-login__secondary {
    margin-top: 1rem;
    text-align: left;
}

/*
 * The block's own box is removed so its parts join the actions row directly. `display: none` on
 * `.nebula-passkey-hidden` still wins while the script has not revealed it, because that rule is
 * `!important` and this one is not.
 */
.nebula-passkey-login-frontend {
    display: contents;
}

.nebula-passkey-login-frontend__divider {
    color: var(--color-text-muted, #575757);
    font-size: 0.85em;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/*
 * The glyph beside the label. Sized here rather than by a theme because the class is this module's:
 * a `nebula-*` class used in a Nebula template has to be defined in Nebula's own CSS, or it is
 * defined only wherever the author happened to be looking. 1.125rem matches the cap height of the
 * label at both Luma's and NFT's button font size.
 */
.nebula-passkey-login-frontend__icon {
    inline-size: 1.125rem;
    block-size: 1.125rem;
    flex: none;
}

/* A message, not a third button: it takes the whole row and pushes below the two that are. */
.nebula-passkey-login-frontend__error {
    flex: 0 0 100%;
    margin: 0;
}

/*
 * Hidden until the script says otherwise, toggled by a class rather than an inline style so a
 * Content Security Policy that forbids inline styles does not leave the button permanently
 * invisible.
 *
 * `!important`, which is not a habit worth forming and is earned here. This class has to beat
 * whatever the merchant's theme says about the element it lands on, and one element it lands on is
 * an error region carrying Luma's `.message.error`. That selector has two classes to this one's
 * one, so it wins on specificity and the error box rendered permanently: measured on Luma, an empty
 * pink bar sat under the password field on every visit to the login page and covered the Show
 * Password control. Raising specificity here would only move the fight to the next theme.
 *
 * It also has to beat `display: contents` on the passkey block above, which is why that rule is
 * written without `!important`.
 */
.nebula-passkey-hidden {
    display: none !important;
}

/* -------------------------------------------------------------- two-step verification, storefront */

.nebula-passkey-challenge {
    max-width: 26rem;
    margin: 0 auto;
}

.nebula-passkey-challenge__intro,
.nebula-passkey-twostep__intro {
    margin-bottom: 1.25rem;
}

.nebula-passkey-twostep > form {
    margin-bottom: 2rem;
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--color-gray-light, #d1d1d1);
}

.nebula-passkey-twostep > form:last-child {
    border-bottom: 0;
}

/*
 * The recovery codes, shown once. Monospaced and widely spaced because they are read off a screen
 * and copied by hand, which is the one moment where legibility is the whole job.
 */
.nebula-passkey-twostep__codes {
    margin-bottom: 2rem;
    padding: 1rem 1.25rem;
    border: 2px solid var(--color-gray-light, #d1d1d1);
    border-radius: 3px;
}

.nebula-passkey-twostep__code-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: 0.35rem 1rem;
    margin: 1rem 0 0;
    padding: 0;
    list-style: none;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 1.05em;
    letter-spacing: 0.04em;
}

.nebula-passkey-twostep__qr img {
    display: block;
    width: 240px;
    height: 240px;
    max-width: 100%;
}

.nebula-passkey-twostep__secret {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 1.1em;
    letter-spacing: 0.08em;
    word-break: break-all;
}

/*
 * The security prompt card.
 *
 * TWO CORRECTIONS TO THE RULE AT THE TOP OF THIS FILE. Both were found by looking
 * at the page rather than by reading the stylesheet, and both are the kind of
 * thing that looks right in one colour scheme and is invisible in the other.
 *
 * 1. `.action.primary` is not a universal class. Luma and Hyva style it; the
 *    Nebula storefront theme does not, and that is the theme this estate ships.
 *    Both buttons rendered as bare underlined text, so the card asked the customer
 *    to act and gave them nothing to press. This component brings its own button,
 *    which is what the estate's own rule says a module should do.
 *
 * 2. `--color-primary` is the wrong token to build a control from. In the Nebula
 *    theme the palette is written with CSS `light-dark()`, and most tokens flip:
 *    `--color-surface` is `light-dark(#fff, #111827)`, `--color-fg` is
 *    `light-dark(#111827, #f3f4f6)`. `--color-primary` does NOT. It is a fixed
 *    `#111827`, which is near-black on a white page and *exactly the dark surface
 *    colour* in dark mode, so a filled button and a filled badge both vanished
 *    into the card they sat on.
 *
 *    `--color-accent` is the one that flips, and flips the right way: dark in
 *    light mode, light in dark mode. Paired with `--color-bg` for its text, which
 *    flips the opposite way, a filled control has contrast in both schemes without
 *    this file knowing which one is active.
 *
 * Literal fallbacks throughout, so a theme carrying none of these tokens still
 * gets a card and a button rather than a paragraph and a hyperlink.
 */

.nebula-pk-prompt {
    --nebula-pk-accent: var(--color-accent, #2f6fed);
    --nebula-pk-on-accent: var(--color-bg, #ffffff);
    --nebula-pk-surface: var(--color-surface, #ffffff);
    --nebula-pk-panel: var(--color-bg, #ffffff);
    --nebula-pk-line: var(--color-border, #d8dce3);
    --nebula-pk-text: var(--color-fg, #1b1f26);
    --nebula-pk-soft: var(--color-muted, #5b6270);
    --nebula-pk-radius: var(--radius-surface, 10px);
    --nebula-pk-radius-control: var(--radius-control, 8px);

    /* The tint is what makes this read as a notice rather than one more panel.
       Mixed from the accent, which flips, so it stays visible in both schemes.
       The plain surface underneath is the fallback where color-mix is not
       supported, and the card keeps its border either way. */
    background: var(--nebula-pk-surface);
    background: color-mix(in srgb, var(--nebula-pk-accent) 8%, var(--nebula-pk-surface));
    border: 1px solid var(--nebula-pk-line);
    border-radius: var(--nebula-pk-radius);
    color: var(--nebula-pk-text);
    padding: 1.5rem;
    margin-block-end: 2rem;
}

.nebula-pk-prompt__head {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin-block-end: 0.75rem;
}

.nebula-pk-prompt__icon {
    display: inline-flex;
    color: var(--nebula-pk-accent);
}

.nebula-pk-prompt__title {
    margin: 0;
    font-size: 1.125rem;
    line-height: 1.3;
}

.nebula-pk-prompt__lead {
    margin: 0 0 1.25rem;
    max-inline-size: 68ch;
}

.nebula-pk-prompt__options {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Side by side where there is room, stacked where there is not. The basis is the
   wrap point, so no media query and no assumption about the column it sits in. */
.nebula-pk-prompt__option {
    flex: 1 1 17rem;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 1rem;
    /* The page background rather than the surface: against a tinted card it reads
       as a raised panel in light mode and a recessed one in dark, and both are a
       clear edge. Using the surface here made the sub-cards disappear into the
       card in dark mode. */
    background: var(--nebula-pk-panel);
    border: 1px solid var(--nebula-pk-line);
    border-radius: var(--nebula-pk-radius-control);
}

/* The recommended option is where a scanner should land, so it carries the accent
   edge. The badge says the same thing in words for anyone who reads instead. */
.nebula-pk-prompt__option--recommended {
    border-color: var(--nebula-pk-accent);
    box-shadow: 0 0 0 1px var(--nebula-pk-accent);
}

.nebula-pk-prompt__option-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
}

.nebula-pk-prompt__option-title {
    font-weight: 600;
}

.nebula-pk-prompt__badge {
    padding: 0.125rem 0.5rem;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.6;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--nebula-pk-on-accent);
    background: var(--nebula-pk-accent);
    border-radius: 999px;
}

.nebula-pk-prompt__option-text {
    margin: 0;
    flex: 1 1 auto;
}

.nebula-pk-prompt__option-meta {
    margin: 0;
    font-size: 0.875rem;
    color: var(--nebula-pk-soft);
}

.nebula-pk-prompt__note {
    margin: 1.25rem 0 0;
    font-size: 0.875rem;
    color: var(--nebula-pk-soft);
}

/* The button, owned here rather than borrowed from a theme. See correction 1. */
.nebula-pk-btn {
    display: inline-block;
    margin-block-start: 0.25rem;
    padding: 0.625rem 1.125rem;
    border: 1px solid transparent;
    border-radius: var(--nebula-pk-radius-control, 8px);
    font-weight: 600;
    line-height: 1.4;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.nebula-pk-btn:focus-visible {
    outline: 2px solid var(--nebula-pk-accent);
    outline-offset: 2px;
}

.nebula-pk-btn--primary,
.nebula-pk-btn--primary:visited {
    background: var(--nebula-pk-accent);
    border-color: var(--nebula-pk-accent);
    color: var(--nebula-pk-on-accent);
}

/* Toward the text colour by a little, which darkens on a light scheme and
   lightens on a dark one, because both tokens flip. */
.nebula-pk-btn--primary:hover {
    background: color-mix(in srgb, var(--nebula-pk-accent) 85%, var(--nebula-pk-text));
    border-color: color-mix(in srgb, var(--nebula-pk-accent) 85%, var(--nebula-pk-text));
    color: var(--nebula-pk-on-accent);
}

.nebula-pk-btn--secondary,
.nebula-pk-btn--secondary:visited {
    background: transparent;
    border-color: var(--nebula-pk-line);
    color: var(--nebula-pk-text);
}

.nebula-pk-btn--secondary:hover {
    border-color: var(--nebula-pk-accent);
    color: var(--nebula-pk-accent);
}
