/* Auth pages — deliberately minimal chrome. Nothing to click but the one
   thing we want clicked. Uses the Velvet Mystery tokens from styles.css. */

.auth-body {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(900px 600px at 50% -10%, rgba(123, 47, 190, 0.22), transparent 70%),
        var(--c-bg-deep);
    padding: var(--s-5);
}

.auth {
    width: 100%;
    max-width: 440px;
    text-align: center;
}

.auth__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--s-3);
    margin-bottom: var(--s-7);
    color: var(--c-text);
    text-decoration: none;
    font-family: var(--f-display);
    font-size: 26px;
    letter-spacing: 0.01em;
}

.auth__title {
    font-family: var(--f-display);
    font-size: clamp(28px, 6vw, 36px);
    line-height: 1.15;
    color: var(--c-text);
    margin: 0 0 var(--s-3);
}

.auth__lede {
    color: var(--c-text-muted);
    line-height: 1.6;
    margin: 0 0 var(--s-6);
}

.auth__form { text-align: left; }

.auth__label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--c-text-soft);
    margin-bottom: var(--s-2);
}

.auth__input {
    width: 100%;
    padding: 15px var(--s-4);
    background: var(--c-bg-card);
    border: 1px solid var(--c-border-hi);
    border-radius: 11px;
    color: var(--c-text);
    font: inherit;
    transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.auth__input::placeholder { color: var(--c-text-soft); }

.auth__input:focus-visible {
    outline: none;
    border-color: var(--c-border-accent);
    box-shadow: 0 0 0 3px rgba(233, 75, 123, 0.16);
}

.auth__submit {
    width: 100%;
    margin-top: var(--s-4);
    justify-content: center;
}

.auth__error {
    margin: var(--s-3) 0 0;
    color: var(--c-accent-hi);
    font-size: 14px;
}

/* Confirmation state, shown in place of the form once the link is away. */
.auth__sent-icon {
    width: 52px;
    height: 52px;
    margin: 0 auto var(--s-4);
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: rgba(123, 47, 190, 0.18);
    border: 1px solid var(--c-border-accent);
    color: var(--c-accent-hi);
}

.auth__sent-title {
    font-family: var(--f-display);
    font-size: 26px;
    color: var(--c-text);
    margin: 0 0 var(--s-3);
}

.auth__sent-body { color: var(--c-text-muted); line-height: 1.6; margin: 0; }
.auth__sent-body strong { color: var(--c-text); }

.auth__spinner {
    width: 34px;
    height: 34px;
    margin: 0 auto var(--s-5);
    border: 3px solid var(--c-border-hi);
    border-top-color: var(--c-accent);
    border-radius: 50%;
    animation: authSpin 0.9s linear infinite;
}

@keyframes authSpin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    .auth__spinner { animation-duration: 3s; }
}

.auth__legal {
    margin: var(--s-6) 0 0;
    font-size: 13px;
    line-height: 1.6;
    color: var(--c-text-soft);
}

.auth__legal a { color: var(--c-text-muted); }

/* ── Onboarding ──────────────────────────────────────────────────────────── */
.auth-body--wide { align-items: flex-start; padding-top: var(--s-7); }
.auth--wide { max-width: 560px; text-align: left; }
.auth--wide .auth__brand { display: flex; justify-content: flex-start; }
.auth--wide .auth__title,
.auth--wide .auth__lede { text-align: left; }

.ob__progress {
    height: 3px;
    background: var(--c-border);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: var(--s-6);
}

.ob__progress span {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, var(--c-violet), var(--c-accent));
    transition: width 0.3s ease;
}

.auth__label--spaced { margin-top: var(--s-5); }

.ob__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin-top: var(--s-2);
}

.ob__chip {
    padding: 10px var(--s-4);
    background: var(--c-bg-card);
    border: 1px solid var(--c-border-hi);
    border-radius: 999px;
    color: var(--c-text-muted);
    font: inherit;
    font-size: 15px;
    cursor: pointer;
    transition: border-color 0.16s ease, background 0.16s ease, color 0.16s ease;
}

.ob__chip:hover { border-color: var(--c-border-accent); color: var(--c-text); }

.ob__chip.is-on {
    background: var(--c-accent);
    border-color: var(--c-accent);
    color: var(--c-text-on-accent);
    font-weight: 600;
}

.ob__back {
    display: block;
    margin: var(--s-4) auto 0;
    background: none;
    border: 0;
    color: var(--c-text-soft);
    font: inherit;
    cursor: pointer;
}

.ob__back:hover { color: var(--c-text-muted); }

/* Photo step */
.ob__photos {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-3);
    margin-bottom: var(--s-4);
}

.ob__photo {
    position: relative;
    aspect-ratio: 4 / 5;
    border-radius: 12px;
    overflow: hidden;
    background: var(--c-bg-card);
    border: 1px solid var(--c-border-hi);
}

.ob__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

.ob__photo-remove {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: 50%;
    background: rgba(14, 10, 20, 0.78);
    color: var(--c-text);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
}

.ob__photo-remove:hover { background: var(--c-accent); color: var(--c-text-on-accent); }

.ob__file {
    position: absolute;
    width: 1px; height: 1px;
    opacity: 0; pointer-events: none;
}

.ob__add-label {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    padding: var(--s-5);
    border: 1px dashed var(--c-border-hi);
    border-radius: 12px;
    color: var(--c-text-muted);
    cursor: pointer;
    transition: border-color 0.16s ease, color 0.16s ease;
}

.ob__add-label:hover { border-color: var(--c-border-accent); color: var(--c-text); }

.ob__count {
    margin: var(--s-2) 0 0;
    font-size: 13px;
    color: var(--c-text-soft);
    text-align: right;
}

/* Google sits above the email form: one tap beats a round trip through an
   inbox, and the inbox hop is where an email-link flow loses people.

   Dark variant rather than Google's white button — a white slab on a velvet
   page read as a foreign object pasted in. Google's brand guidelines allow a
   dark theme provided the logo keeps its colours and is not recoloured, which
   it does here. */
.auth__google {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-3);
    padding: 15px var(--s-4);
    background: var(--c-bg-card);
    color: var(--c-text);
    border: 1px solid var(--c-border-hi);
    border-radius: 11px;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.16s ease, background 0.16s ease;
}

.auth__google:hover {
    border-color: var(--c-border-accent);
    background: var(--c-bg-card-hi);
}

.auth__google:disabled { opacity: 0.55; cursor: default; }

/* The logo keeps a light chip behind it so the coloured marks stay legible on
   a dark surface without being recoloured. */
.auth__google svg {
    flex: 0 0 auto;
    background: #fff;
    border-radius: 3px;
    padding: 2px;
    box-sizing: content-box;
}

.auth__or {
    position: relative;
    text-align: center;
    margin: var(--s-5) 0;
    color: var(--c-text-soft);
    font-size: 13px;
}

.auth__or::before {
    content: "";
    position: absolute;
    left: 0; right: 0; top: 50%;
    border-top: 1px solid var(--c-border);
}

.auth__or span { position: relative; background: var(--c-bg-deep); padding: 0 var(--s-3); }

/* ── Verification, on the way out ──────────────────────────────────────────
   Signup used to end on "You're in" and a store button, which stopped being
   true when the app started gating unverified accounts: the next thing that
   happens to a web signup is a wall nobody warned them about. This card is
   the app's gate said once, early, next to the button that takes them there.
   It sits above the store link for the same reason it does in the app - the
   reason for an action belongs on the screen that asks for it. */
.verify-card {
    margin-top: var(--s-5);
    padding: var(--s-5);
    background: var(--c-bg-card);
    border: 1px solid var(--c-border);
    border-radius: 16px;
    text-align: left;
}

.verify-card__title {
    margin: 0 0 var(--s-4);
    font-size: 17px;
    font-weight: 700;
    color: var(--c-text);
}

.verify-card__row {
    display: flex;
    gap: var(--s-3);
    align-items: flex-start;
}

.verify-card__row + .verify-card__row { margin-top: var(--s-4); }

.verify-card__dot {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    margin-top: 1px;
    border-radius: 999px;
    background: var(--c-violet-deep);
    color: var(--c-accent-hi);
    display: flex;
    align-items: center;
    justify-content: center;
}

.verify-card__text {
    margin: 0;
    font-size: 15px;
    line-height: 1.55;
    color: var(--c-text-muted);
}

.verify-card__text strong { color: var(--c-text); font-weight: 600; }

.verify-card__privacy {
    display: flex;
    gap: var(--s-2);
    align-items: flex-start;
    margin: var(--s-4) 0 0;
    padding-top: var(--s-4);
    border-top: 1px solid var(--c-border);
    font-size: 14px;
    line-height: 1.5;
    color: var(--c-text-soft);
}

.verify-card__privacy svg { flex: 0 0 auto; margin-top: 2px; }

/* ── Selfie verification ───────────────────────────────────────────────────
   The camera lives on the web now, not only in the app. One page, one state
   at a time: the case, the camera, the captured photo, and whatever the
   review came back with. */
.vf__stage {
    position: relative;
    width: 100%;
    max-width: 320px;
    margin: var(--s-5) auto 0;
    aspect-ratio: 1 / 1;
    border-radius: 999px;
    overflow: hidden;
    background: var(--c-bg-card);
    border: 2px solid var(--c-accent);
}

.vf__stage video,
.vf__stage img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Front cameras show a mirrored preview everywhere else, and an unmirrored
   one reads as somebody else's face. The capture is mirrored to match, so
   what is sent is what was on screen. */
.vf__stage video { transform: scaleX(-1); }

.vf__hint {
    margin: var(--s-4) 0 0;
    font-size: 14px;
    line-height: 1.5;
    color: var(--c-text-soft);
    text-align: center;
}

.vf__actions { margin-top: var(--s-5); }
.vf__actions .btn + .btn { margin-top: var(--s-2); }

.vf__status {
    margin: var(--s-5) auto 0;
    max-width: 420px;
    padding: var(--s-5);
    background: var(--c-bg-card);
    border: 1px solid var(--c-border);
    border-radius: 16px;
}

.vf__status--bad { border-color: var(--c-border-accent); }

.vf__status-label {
    margin: 0 0 var(--s-2);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--c-text-soft);
    text-align: left;
}

.vf__status-text {
    margin: 0;
    font-size: 15px;
    line-height: 1.55;
    color: var(--c-text);
    text-align: left;
}

.vf__note {
    margin: var(--s-3) 0 0;
    font-size: 14px;
    line-height: 1.5;
    color: var(--c-text-muted);
    text-align: left;
}

.vf__bar {
    height: 6px;
    margin-top: var(--s-4);
    border-radius: 999px;
    background: var(--c-bg-card-hi);
    overflow: hidden;
}

.vf__bar span {
    display: block;
    width: 40%;
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--c-violet), var(--c-accent));
    animation: vfSlide 1.6s ease-in-out infinite;
}

@keyframes vfSlide {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(250%); }
}

@media (prefers-reduced-motion: reduce) {
    .vf__bar span { animation: none; width: 100%; }
}
