/* ============================================================
   account.css — sign in, sign up, password reset.

   Same design system as yuzutrace.css: cool near-white sheet, navy house
   ink, cyan highlighter, Instrument Serif over Inter with IBM Plex Mono
   for metadata and controls. Replaces the legacy YuzuTrace auth.css.

   Every id and class the markup carries is required by public/js/auth.js
   (form ids, .alert, .button-text, .spinner, .fa-eye toggling). Presentation
   changed; contract did not.
   ============================================================ */

:root {
    --void:   #f5f6f7;
    --panel:  #ffffff;
    --bone:   #0f1113;
    --bone-2: #4a5057;
    --bone-3: #858c93;

    --pen:      #16365c;
    --pen-deep: #0f2540;
    --chalk:    #02d1f1;
    --chalk-ink:#0a6f83;

    --ok:   #1f7a4d;
    --warn: #a85f00;
    --bad:  #c1272d;

    --hair:      rgba(15,17,19,.16);
    --hair-firm: rgba(15,17,19,.32);

    --display: 'Instrument Serif', 'Times New Roman', serif;
    --sans:    'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
    --mono:    'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

    /* Aliases kept for reset-password.html, whose inline styles are written
       against the old auth.css names. Mapping them here means that page can
       adopt this sheet without rewriting logic that is inline and fragile. */
    --primary:    var(--pen);
    --text-muted: var(--bone-3);
    --success:    var(--ok);
    --error:      var(--bad);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0; min-height: 100vh;
    background: var(--void); color: var(--bone);
    font-family: var(--sans); font-size: 16px; line-height: 1.6;
    -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--pen); outline-offset: 3px; }
::selection { background: var(--chalk); color: var(--bone); }

/* ---------- Loader ---------- */

#app-loader {
    position: fixed; inset: 0; z-index: 900;
    display: grid; place-content: center; justify-items: center; gap: 1.2rem;
    background: var(--void);
}
#app-loader.hidden, #app-loader[hidden] { display: none; }
.spinner-ring {
    width: 34px; height: 34px; border-radius: 50%;
    border: 2px solid var(--hair); border-top-color: var(--pen);
    animation: spin .8s linear infinite;
}
.loader-text { font-family: var(--mono); font-size: .68rem; letter-spacing: .18em; text-transform: uppercase; color: var(--bone-3); }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner-ring { animation-duration: 2.4s; } }

/* ---------- Frame ---------- */

.auth-container {
    min-height: 100vh;
    display: grid; align-content: center; justify-items: center;
    padding: clamp(1.5rem, 5vw, 3.5rem) clamp(1.25rem, 4vw, 2.5rem);
}

/* The card sits off-axis on wide screens, with a marginal note to its left —
   the same annotation device the home page uses. */
.auth-box {
    width: 100%; max-width: 460px;
    min-width: 0;             /* never widened by a child that will not shrink */
    position: relative;
}

.auth-box--wide { max-width: 560px; }

/* Marginal note, set from data-note so each page names itself. */
.auth-box::before {
    content: attr(data-note);
    display: none;
    position: absolute; top: .35rem; right: calc(100% + 2.5rem);
    font-family: var(--mono); font-size: .64rem; letter-spacing: .18em;
    text-transform: uppercase; color: var(--bone-3); white-space: nowrap;
}
@media (min-width: 1080px) { .auth-box::before { display: block; } }

/* ---------- The three payment outcomes ----------
   Paid, cancelled, failed. The colour is carried by the heading and its
   marginal note, not by the whole card: the state is one sentence long and
   tinting everything would drown the page in it.

   Colour is never the only signal — the words say it too ("Payment received",
   "Payment cancelled", "Payment problem"), so a reader who cannot separate
   green from orange loses nothing.

   Contrast on --void (#f5f6f7), all AA for normal text and far above the
   3:1 a heading of this size would need:
     --ok   #1f7a4d   4.91:1
     --warn #a85f00   4.51:1
     --bad  #c1272d   5.40:1  */
.auth-box--good .auth-header h1 { color: var(--ok); }
.auth-box--warn .auth-header h1 { color: var(--warn); }
.auth-box--bad  .auth-header h1 { color: var(--bad); }

.auth-box--good::before { color: var(--ok); }
.auth-box--warn::before { color: var(--warn); }
.auth-box--bad::before  { color: var(--bad); }

/* ---------- Header ---------- */

.auth-header { margin-bottom: 2.25rem; }

.auth-back-link {
    display: inline-flex; align-items: center; gap: .5rem;
    font-family: var(--mono); font-size: .66rem; letter-spacing: .14em;
    text-transform: uppercase; text-decoration: none; color: var(--bone-3);
    margin-bottom: 2.5rem; transition: color .16s ease;
}
.auth-back-link:hover { color: var(--pen); }
.auth-back-link svg { width: 13px; height: 13px; }

.auth-header .logo-icon { margin-bottom: 1.75rem; }
/* The logo is a wordmark, not a square mark: never crop a wordmark into a
   circle. Any container around it stays transparent and auto-width, and the
   image is contained, never covered. */
.auth-header .logo-icon,
.auth-header .logo-icon picture {
    display: block; width: auto; height: 30px;
    background: none; border: 0; border-radius: 0; box-shadow: none; overflow: visible;
}
.auth-header .logo-icon img { height: 30px; width: auto; object-fit: contain; }

.auth-header h1 {
    font-family: var(--display); font-weight: 400;
    font-size: clamp(2.1rem, 5vw, 2.7rem); line-height: 1.05; letter-spacing: -.015em;
    margin: 0 0 .65rem;
}
.auth-header p { margin: 0; font-size: .94rem; color: var(--bone-2); }

.btn-link { color: var(--pen); text-decoration: none; border-bottom: 1px solid var(--hair-firm); padding-bottom: 1px; }
.btn-link:hover { border-color: var(--pen); }

.auth-language-selector {
    margin-top: 1.75rem; padding-top: 1.5rem; border-top: 1px solid var(--hair);
    font-family: var(--mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase;
    color: var(--bone-3);
}
.auth-language-selector a { text-decoration: none; color: var(--bone-3); }
.auth-language-selector a:hover { color: var(--bone); }
.auth-language-selector a.active { color: var(--pen); }
.auth-language-selector .separator { margin: 0 .5rem; opacity: .5; }

.magic-intro { font-size: .94rem; line-height: 1.6; color: var(--bone-2); margin: 0 0 1.75rem; }

/* ---------- Forms ---------- */

/* min-width:0 because a grid or flex item defaults to min-width:auto and
   refuses to shrink below its widest child — which is how one stubborn
   element drags the whole card past the edge of the screen. */
.auth-form { display: none; min-width: 0; }
.auth-form.active { display: block; }

.form-group { margin-bottom: 1.35rem; }
.form-group label {
    display: block; margin-bottom: .5rem;
    font-family: var(--mono); font-size: .64rem; letter-spacing: .16em;
    text-transform: uppercase; color: var(--bone-3);
}

.input-wrapper { position: relative; }
.input-wrapper .input-icon {
    position: absolute; left: .95rem; top: 50%; transform: translateY(-50%);
    width: 16px; height: 16px; color: var(--bone-3); pointer-events: none;
}
.input-wrapper input {
    width: 100%; font: inherit; font-size: .97rem; color: var(--bone);
    background: var(--panel);
    border: 1px solid var(--hair-firm); border-radius: 2px;
    padding: .92rem 1rem .92rem 2.75rem;
    transition: border-color .16s ease, box-shadow .16s ease;
}
.input-wrapper input::placeholder { color: var(--bone-3); }
.input-wrapper input:focus {
    outline: none; border-color: var(--pen);
    box-shadow: 0 0 0 3px rgba(22,54,92,.10);
}
.input-wrapper input:has(~ .toggle-password) { padding-right: 3rem; }

.toggle-password {
    position: absolute; right: .55rem; top: 50%; transform: translateY(-50%);
    background: none; border: 0; cursor: pointer; padding: .45rem;
    color: var(--bone-3); line-height: 0;
}
.toggle-password:hover { color: var(--pen); }
/* auth.js swaps .fa-eye / .fa-eye-slash on the inner element; CSS decides
   which glyph shows, so the icon font is never needed. */
.toggle-password i { display: block; font-style: normal; }
.toggle-password svg { width: 17px; height: 17px; }
.toggle-password .fa-eye .ico-off,
.toggle-password i:not(.fa-eye-slash) .ico-off { display: none; }
.toggle-password i.fa-eye-slash .ico-off { display: block; }
.toggle-password i.fa-eye-slash .ico-on  { display: none; }

/* Two fields side by side on anything wider than a phone. */
.form-row { display: grid; gap: 0 1rem; }
@media (min-width: 460px) { .form-row { grid-template-columns: 1fr 1fr; } }

/* ---------- Password strength ----------
   auth.js sets .password-strength-fill's width and swaps its level class
   (weak / fair / good / strong), and writes into .strength-text. It also
   toggles display on #passwordStrength itself, so no display rule here. */

.password-strength { margin-top: .7rem; }
.password-strength-track { height: 3px; background: var(--hair); border-radius: 2px; overflow: hidden; }
.password-strength-fill {
    height: 100%; width: 0; border-radius: 2px;
    background: var(--bone-3);
    transition: width .2s ease, background .2s ease;
}
.password-strength-fill.weak   { background: var(--bad); }
.password-strength-fill.fair   { background: #c47000; }
.password-strength-fill.good   { background: #7d7a2e; }
.password-strength-fill.strong { background: var(--ok); }
.strength-text {
    display: block; margin-top: .45rem;
    font-family: var(--mono); font-size: .62rem; letter-spacing: .14em;
    text-transform: uppercase; color: var(--bone-3);
}

/* ---------- Password requirements ----------
   auth.js hides each rule as it is satisfied (display none/flex) and hides
   the whole block once all four pass — so this is a shrinking checklist,
   not a list of ticks. */

.password-requirements { margin-top: .85rem; }
.requirements-title {
    margin: 0 0 .5rem;
    font-family: var(--mono); font-size: .6rem; letter-spacing: .16em;
    text-transform: uppercase; color: var(--bone-3);
}
.requirements-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.requirement {
    display: flex; align-items: center; gap: .5rem;
    font-size: .84rem; color: var(--bone-2);
}
.requirement::before {
    content: ""; flex: none;
    width: 5px; height: 5px; border-radius: 50%; background: var(--bone-3);
}

/* ---------- Consent ---------- */

.form-group--consent { display: grid; gap: .85rem; margin: 1.75rem 0 1.5rem; }
.checkbox-label {
    display: grid; grid-template-columns: auto 1fr; gap: .7rem; align-items: start;
    font-size: .88rem; line-height: 1.5; color: var(--bone-2); cursor: pointer;
}
.checkbox-label input[type="checkbox"] {
    width: 17px; height: 17px; margin: .15rem 0 0;
    accent-color: var(--pen); cursor: pointer;
}
.checkbox-label a { color: var(--pen); text-decoration: underline; text-underline-offset: 2px; }

.form-actions {
    display: flex; flex-wrap: wrap; gap: .5rem 1.5rem;
    justify-content: space-between; align-items: baseline;
    margin: -.35rem 0 1.5rem;
}
.link-text {
    font-family: var(--mono); font-size: .64rem; letter-spacing: .12em;
    text-transform: uppercase; text-decoration: none; color: var(--bone-3);
}
.link-text:hover { color: var(--pen); }

/* ---------- Buttons ---------- */

.btn-primary, .btn-google {
    position: relative; width: 100%;
    display: inline-flex; align-items: center; justify-content: center; gap: .65rem;
    font-family: var(--mono); font-size: .74rem; letter-spacing: .14em; text-transform: uppercase;
    padding: 1.02rem 1.5rem; border-radius: 2px; cursor: pointer;
    transition: background .16s ease, color .16s ease, border-color .16s ease;
}

.btn-primary { background: var(--pen); border: 1px solid var(--pen); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--pen-deep); border-color: var(--pen-deep); }
.btn-primary:disabled { opacity: .55; cursor: not-allowed; }

.btn-google { background: var(--panel); border: 1px solid var(--hair-firm); color: var(--bone); }
.btn-google:hover:not(:disabled) { border-color: var(--pen); }
.btn-google svg { flex: none; }

.btn-primary .spinner, .btn-google .spinner {
    display: none;
    width: 15px; height: 15px; border-radius: 50%;
    border: 2px solid rgba(255,255,255,.35); border-top-color: #fff;
    animation: spin .7s linear infinite;
}
.btn-google .spinner { border-color: var(--hair); border-top-color: var(--pen); }
.btn-primary.loading .spinner, .btn-google.loading .spinner { display: block; }
.btn-primary.loading .button-text, .btn-google.loading .button-text { display: none; }

/* ---------- Divider ---------- */

.auth-divider {
    display: flex; align-items: center; gap: 1rem;
    margin: 1.5rem 0;
    font-family: var(--mono); font-size: .62rem; letter-spacing: .18em;
    text-transform: uppercase; color: var(--bone-3);
}
.auth-divider::before, .auth-divider::after { content: ""; flex: 1; height: 1px; background: var(--hair); }

/* ---------- Alerts ---------- */

.alert {
    display: none;
    padding: .85rem 1rem; margin-bottom: 1.25rem; border-radius: 2px;
    font-size: .9rem; line-height: 1.5;
    border-left: 3px solid transparent;
}
.alert.show, .alert.active { display: block; }
.alert-error   { background: rgba(193,39,45,.07); border-left-color: var(--bad); color: #8f1d22; }
.alert-success { background: rgba(31,122,77,.08); border-left-color: var(--ok); color: #15583a; }

/* ---------- reCAPTCHA ---------- */

/* Google renders the checkbox in a 304px iframe with the width hard-coded on
   the element. It is the one thing on this page that cannot shrink, so on a
   narrow phone it stops being a widget in a card and becomes the width of the
   page: the card centres inside a body wider than the viewport, and every
   field gets clipped on the right.
   Scaling it is the only lever — the iframe is cross-origin, its contents are
   not ours to restyle. */
.recaptcha-container {
    display: flex; justify-content: center; margin-bottom: 1.25rem;
    max-width: 100%; overflow: hidden;
}
.recaptcha-container:empty { margin-bottom: 0; }

@media (max-width: 400px) {
    .recaptcha-container { justify-content: flex-start; height: 66px; }
    .recaptcha-container > div {
        transform: scale(.86); transform-origin: left top;
    }
}

/* ---------- Reset form footer ---------- */

.form-footer { margin-top: 1.5rem; text-align: center; font-size: .9rem; color: var(--bone-2); }
.form-footer p { margin: 0; }


/* ============================================================
   verify-email.html — the page reached from the confirmation link.
   It has its own markup and its own inline script, so these class names
   are its contract; only the presentation is ours.
   ============================================================ */

.verification-container {
    min-height: 100vh; display: grid; align-content: center; justify-items: center;
    text-align: center; padding: clamp(1.5rem, 5vw, 3.5rem);
}
.verification-title {
    font-family: var(--display); font-weight: 400;
    font-size: clamp(1.9rem, 4.5vw, 2.5rem); line-height: 1.08; margin: 1.5rem 0 .75rem;
}
.verification-message { font-size: .97rem; line-height: 1.65; color: var(--bone-2); max-width: 46ch; margin: 0 auto 2rem; }

/* Three states, one at a time — the inline script toggles .hidden. */
.hidden { display: none !important; }

.loading-icon, .success-icon, .error-icon {
    width: 54px; height: 54px; display: grid; place-items: center;
    border: 1px solid var(--hair-firm); border-radius: 50%; margin: 0 auto;
}
.loading-icon { border-top-color: var(--pen); animation: spin .8s linear infinite; }
.success-icon { border-color: var(--ok); color: var(--ok); }
.error-icon   { border-color: var(--bad); color: var(--bad); }
.success-icon::before { content: '✓'; font-size: 1.5rem; line-height: 1; }
.error-icon::before   { content: '!'; font-size: 1.5rem; line-height: 1; font-weight: 600; }

.verification-container .btn-primary { width: auto; min-width: 220px; }


/* ============================================================
   Payment outcome pages. Same sheet as the auth pages: these are read
   at a charged moment — just after paying, or just after backing out —
   and the last thing they should do is look like a different product.
   ============================================================ */

.outcome {
    border: 1px solid var(--hair-firm); border-left-width: 3px;
    padding: 1.4rem 1.5rem; margin: 0 0 1.75rem;
}
.outcome--good    { border-left-color: var(--ok); }
.outcome--neutral { border-left-color: var(--pen); }
.outcome--bad     { border-left-color: var(--bad); }

.outcome h2 {
    font-family: var(--mono); font-size: .66rem; font-weight: 500;
    letter-spacing: .16em; text-transform: uppercase; color: var(--bone-3);
    margin: 0 0 .7rem;
}
.outcome p { margin: 0; font-size: .95rem; line-height: 1.65; color: var(--bone-2); }

/* Numbered stages, echoing the method section on the home page. */
.steplist { list-style: none; margin: 0; padding: 0; display: grid; gap: .9rem; }
.steplist li { display: grid; grid-template-columns: 2.2rem 1fr; gap: .4rem; align-items: baseline; }
.steplist__num { font-family: var(--mono); font-size: .68rem; color: var(--pen); }
.steplist span:last-child { font-size: .94rem; line-height: 1.6; color: var(--bone-2); }

.countdown { font-family: var(--mono); font-size: .66rem; letter-spacing: .14em; text-transform: uppercase; color: var(--bone-3); }
.countdown span { color: var(--pen); }

/* On these pages the button is the only action — let it fill the card. */
.auth-container .btn-primary { display: flex; text-decoration: none; }


/* The resend control is the one button on this page that actually does
   something, and it inherited .btn-primary's white text on a transparent
   ground — white on the light sheet. A rule rather than an inline style: the
   page is generated, and inline overrides get lost on the next edit.

   Disabled during the cooldown it must still be READABLE: the reader needs to
   know it exists and that waiting is the instruction. */
#resendEmailBtn {
    background: transparent;
    color: var(--pen);
    border: 1px solid var(--hair-firm);
    box-shadow: none;
}
#resendEmailBtn:hover:not(:disabled) { background: var(--pen); color: #fff; border-color: var(--pen); }
#resendEmailBtn:disabled { opacity: 1; color: var(--bone-2); border-color: var(--hair); cursor: default; }

/* The escape hatch was a bare browser button. */
#logoutBtn {
    background: none; border: 0; cursor: pointer; padding: .4rem 0;
    font-size: .9rem; color: var(--bone-2);
    text-decoration: underline; text-underline-offset: 3px;
}
#logoutBtn:hover { color: var(--pen); }
