/* login.css — standalone login page (server-rendered login.html + login.js).
   Self-contained: the page never loads home.css, so the shell's oklch theme
   tokens are mirrored here by formula (same --lightness/--hue-offset flip as
   home.css :root / html.dark) to keep the palette byte-identical with the app
   chrome in both modes. DARK is the no-JS default (matches the shell's
   colourMode-cookie default); login.js stamps html.light when the shared
   cookie says light. Brand constants (accent + wordmark blues) match the
   sidebar SYGNAL wordmark / icon.svg. */

:root {
    /* dark by default — the shell's html.dark values */
    --lightness: 0.25;
    --hue-offset: -27;
    --chroma-offset: 0.01;

    --white: oklch(from oklch(100% 0 271.152 / 1) abs(calc(1 - var(--lightness) - l)) calc(c + var(--chroma-offset)) calc(h + var(--hue-offset)) / alpha);
    --black: oklch(from oklch(0% 0 0 / 1) abs(calc(1 - var(--lightness) - l)) c h / alpha);
    --bg: oklch(from oklch(93.403% 0.00011 271.152 / 1) abs(calc(1 - var(--lightness) - l)) calc(c + var(--chroma-offset)) calc(h + var(--hue-offset)) / alpha);
    --bg-1: oklch(from oklch(95.213% 0.00011 271.152 / 1) abs(calc(1 - var(--lightness) - l)) calc(c + var(--chroma-offset)) calc(h + var(--hue-offset)) / alpha);
    --bg-2: oklch(from oklch(91.279% 0.0001 271.152 / 1) abs(calc(1 - var(--lightness) - l)) calc(c + var(--chroma-offset)) calc(h + var(--hue-offset)) / alpha);

    --accent: #73186c;
    --accent-light: #cc84cb;
    --hover: #a961a3;
    --brand-blue: #3e5caa;
    --brand-sky: #7fb6e2;
    --red: oklch(65.28% 0.19116 24.071);
    --err: var(--red);

    --text: var(--black);
    --text-muted: color-mix(in oklch, var(--black) 58%, transparent);
    --border: color-mix(in oklch, currentColor 15%, transparent);
    --rounding: 4px;
    --rounding-big: 0.5rem;
    --font: 'Red Hat', system-ui, sans-serif;
    --font-display: 'Red Hat Display', 'Red Hat', system-ui, sans-serif;
    --mono: 'Red Hat Mono', ui-monospace, 'Roboto Mono', monospace;
}

html.light {
    --lightness: 1;
    --hue-offset: 0;
    --chroma-offset: 0;
}

* {
    box-sizing: border-box;
}

.hidden {
    display: none !important;
}

html {
    height: 100%;
    font-family: var(--font);
    background: var(--bg);
    color: var(--text);
}

/* ── backdrop: console-dark stage — faint dot grid + vignette, with two very
      soft brand glows drifting behind the card (pure CSS, reduced-motion
      aware). ─────────────────────────────────────────────────────────────── */
body {
    margin: 0;
    position: absolute;
    inset: 0;
    overflow: auto;
    background-color: var(--bg);
    background-image:
        radial-gradient(ellipse 120% 90% at 50% 110%, color-mix(in oklch, var(--white) 55%, transparent) 0%, transparent 60%),
        radial-gradient(circle at 1px 1px, color-mix(in oklch, var(--black) 7%, transparent) 1px, transparent 1.5px);
    background-size: 100% 100%, 26px 26px;
}

body::before,
body::after {
    content: "";
    position: fixed;
    width: 55vmax;
    height: 55vmax;
    border-radius: 50%;
    pointer-events: none;
    filter: blur(90px);
    z-index: 0;
}

body::before {
    top: -22vmax;
    left: -14vmax;
    background: radial-gradient(circle, color-mix(in oklch, var(--accent) 26%, transparent), transparent 65%);
    animation: login-drift-a 52s ease-in-out infinite alternate;
}

body::after {
    bottom: -24vmax;
    right: -16vmax;
    background: radial-gradient(circle, color-mix(in oklch, var(--brand-blue) 24%, transparent), transparent 65%);
    animation: login-drift-b 64s ease-in-out infinite alternate;
}

html.light body::before {
    background: radial-gradient(circle, color-mix(in oklch, var(--accent) 13%, transparent), transparent 65%);
}

html.light body::after {
    background: radial-gradient(circle, color-mix(in oklch, var(--brand-blue) 12%, transparent), transparent 65%);
}

@keyframes login-drift-a {
    to {
        transform: translate3d(9vmax, 6vmax, 0) scale(1.12);
    }
}

@keyframes login-drift-b {
    to {
        transform: translate3d(-8vmax, -7vmax, 0) scale(1.08);
    }
}

/* ── centering ────────────────────────────────────────────────────────────── */
#loginCont {
    position: relative;
    z-index: 1;
    min-height: 100%;
    display: grid;
    place-items: center;
    padding: 2rem 1rem;
}

/* ── the console panel ────────────────────────────────────────────────────── */
/* #claimForm is the first-run claim form (login.html {{if .Claim}}). It is the
   same panel wearing a different id, so it is listed alongside #loginForm in
   every rule below rather than restyled — the two must never drift apart. */
#loginForm,
#claimForm {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    width: min(100%, 22.5rem);
    padding: 2.1rem 2rem 1.4rem;
    background: var(--bg-1);
    border: 1px solid var(--border);
    border-radius: var(--rounding-big);
    box-shadow:
        0 24px 60px -24px rgba(0, 0, 0, 0.5),
        0 2px 10px -4px rgba(0, 0, 0, 0.25);
    animation: login-enter 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

/* brand hairline across the top edge — the wordmark's sky→blue→magenta run */
#loginForm::before,
#claimForm::before {
    content: "";
    position: absolute;
    top: -1px;
    left: 1.25rem;
    right: 1.25rem;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, transparent, var(--brand-sky) 18%, var(--brand-blue) 50%, var(--accent-light) 82%, transparent);
    opacity: 0.85;
}

@keyframes login-enter {
    from {
        opacity: 0;
        transform: translateY(12px);
    }
}

/* ── brand block ──────────────────────────────────────────────────────────── */
.login-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    margin-bottom: 0.4rem;
    text-align: center;
}

.login-mark {
    height: 4rem;
    width: 4rem;
    filter: drop-shadow(0 0 18px color-mix(in oklch, var(--brand-blue) 35%, transparent));
}

.login-wordmark {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 900;
    letter-spacing: 0.42em;
    text-indent: 0.42em; /* recentre: tracking pads the right edge only */
    background: linear-gradient(90deg, var(--brand-sky), var(--brand-blue) 45%, var(--accent-light));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.login-sub {
    margin: 0;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* ── first-run claim note ─────────────────────────────────────────────────────
      The one block of prose on this page: it tells the operator which account
      they are about to take and that anyone else on the network could take it
      first. Toned down from .login-error (this is not a failure) but heavier
      than .login-sub, because it must actually be read. */
.login-note {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.45;
    padding: 0.6rem 0.7rem;
    border-radius: var(--rounding);
    color: var(--text-muted);
    background: color-mix(in oklch, var(--brand-blue) 12%, transparent);
    border: 1px solid color-mix(in oklch, var(--brand-blue) 32%, transparent);
}

.login-note strong {
    color: var(--text);
}

/* ── fields ───────────────────────────────────────────────────────────────── */
.login-field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.login-label {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-muted);
}

#loginForm select,
#loginForm input,
#claimForm input {
    width: 100%;
    font-family: var(--font);
    font-size: 1rem;
    color: var(--text);
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--rounding);
    padding: 0.6rem 0.8rem;
    transition: border-color 0.15s, box-shadow 0.15s, background-color 0.15s;
    appearance: none;
}

#loginForm select:focus,
#loginForm input:focus,
#claimForm input:focus {
    outline: none;
    border-color: var(--accent-light);
    box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 22%, transparent);
}

#loginForm input::placeholder,
#claimForm input::placeholder {
    color: color-mix(in oklch, var(--black) 32%, transparent);
    opacity: 1; /* Firefox */
}

#loginForm select {
    cursor: pointer;
    background-image: url(/gui/icons/chevron-down.svg);
    background-repeat: no-repeat;
    background-position: right 0.7rem center;
    background-size: 14px;
    padding-right: 2.3rem;
}

/* dropdown panel entries (UA-rendered; keep them on-theme) */
option {
    font-family: var(--font);
    color: var(--text);
    background: var(--bg-1);
}

/* password + reveal toggle */
.login-password {
    position: relative;
    display: flex;
}

.login-password input {
    flex: 1;
    padding-right: 2.7rem;
}

.login-reveal {
    position: absolute;
    right: 0.3rem;
    top: 50%;
    transform: translateY(-50%);
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: none;
    background: transparent;
    border-radius: var(--rounding);
    cursor: pointer;
}

/* Baked-colour icon swap (login has no sprite): .showing swaps eye -> eye-off. */
.login-reveal::before {
    content: "";
    display: block;
    width: 1.1rem;
    height: 1.1rem;
    margin: 0 auto;
    background: url(/gui/icons/eye.svg) center / contain no-repeat;
    transition: filter 0.15s;
}


.login-reveal.showing::before {
    background-image: url(/gui/icons/eye-off.svg);
    filter: none;
}

/* MFA code — mono, spaced like the chip idiom used across the app */
#totp {
    font-family: var(--mono);
    letter-spacing: 0.3em;
}

/* ── inline error (filled by login.js; no-JS failures still round-trip the
      server redirect exactly as before) ─────────────────────────────────── */
.login-error {
    margin: 0;
    font-size: 0.78rem;
    line-height: 1.35;
    padding: 0.5rem 0.65rem;
    border-radius: var(--rounding);
    color: var(--err);
    background: color-mix(in oklch, var(--err) 14%, transparent);
    border: 1px solid color-mix(in oklch, var(--err) 45%, transparent);
}

#loginForm.shake,
#claimForm.shake {
    animation: login-shake 0.35s ease-in-out;
}

@keyframes login-shake {

    20%,
    60% {
        transform: translateX(-6px);
    }

    40%,
    80% {
        transform: translateX(6px);
    }
}

/* ── submit ───────────────────────────────────────────────────────────────── */
#submit,
#claimSubmit {
    margin-top: 0.25rem;
    width: 100%;
    padding: 0.7rem 1rem;
    font-family: var(--font);
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: white;
    background: var(--accent);
    border: none;
    border-radius: var(--rounding);
    cursor: pointer;
    transition: background-color 0.15s, box-shadow 0.2s, transform 0.12s;
}

#submit:hover:not([disabled]),
#claimSubmit:hover:not([disabled]) {
    background: var(--hover);
    box-shadow: 0 6px 20px -8px color-mix(in oklch, var(--accent) 70%, transparent);
}

#submit:active:not([disabled]),
#claimSubmit:active:not([disabled]) {
    transform: translateY(1px);
}

#submit[disabled],
#claimSubmit[disabled] {
    opacity: 0.75;
    cursor: default;
}

/* pending spinner (login.js toggles .busy on the form during the fetch) */
#loginForm.busy #submit::after,
#claimForm.busy #claimSubmit::after {
    content: "";
    display: inline-block;
    width: 0.85em;
    height: 0.85em;
    margin-left: 0.5em;
    vertical-align: -0.12em;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: white;
    border-radius: 50%;
    animation: login-spin 0.7s linear infinite;
}

@keyframes login-spin {
    to {
        transform: rotate(360deg);
    }
}

/* ── footer ───────────────────────────────────────────────────────────────── */
.login-foot {
    display: flex;
    justify-content: center;
    min-height: 0.8rem;
}

.login-version {
    font-family: var(--mono);
    font-size: 0.62rem;
    letter-spacing: 0.08em;
    color: var(--text-muted);
}

.login-version:empty {
    display: none;
}

/* ── focus + motion etiquette ─────────────────────────────────────────────── */
:focus-visible {
    outline: 1px solid var(--accent-light);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {

    body::before,
    body::after,
    #loginForm,
    #loginForm.shake,
    #claimForm,
    #claimForm.shake {
        animation: none;
    }
}

/* ── small screens ────────────────────────────────────────────────────────── */
@media (max-width: 420px) {

    #loginForm,
    #claimForm {
        padding: 1.7rem 1.3rem 1.1rem;
    }

    .login-mark {
        height: 3.4rem;
        width: 3.4rem;
    }
}
