/* AdRefresh v28 — auth.css (page group "auth", dark theme)
   Serves: users/login.html, users/signup.html,
           registration/password_reset_form.html, password_reset_done.html, password_reset_confirm.html,
           password_reset_complete.html, registration/account_activation_invalid.html.
   Builds on app.css: .v-auth / .v-auth__* (layout), .v-panel--glass (card), .v-btn, .v-eyebrow, .v-gradient-text and
   the crispy/Bootstrap form reskin. Everything here is prefixed auth- (no Bootstrap roots, no new v- classes).
   Only token colours (color-mix over tokens where the landing uses a tinted literal). */

/* ── stage: the hero's backdrop (soft blue glow + 28 px dot grid, faded at the edges) behind the card ── */
.auth-stage{
  position:relative; isolation:isolate; overflow:clip;
  min-height:calc(100vh - var(--nav-h));
  min-height:calc(100svh - var(--nav-h));
  --auth-glow-at:50% 46%;     /* centred behind the card; the split layout moves it behind the visual */
  background:
    radial-gradient(44% 54% at var(--auth-glow-at), color-mix(in srgb, var(--blue) 15%, transparent), transparent 72%),
    radial-gradient(32% 40% at 16% 26%, color-mix(in srgb, var(--cyan) 5%, transparent), transparent 70%),
    var(--bg);
}
.auth-stage::before{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  background:radial-gradient(circle, color-mix(in srgb, var(--blue-hi) 17%, transparent) 1px, transparent 1.5px) 0 0/28px 28px;
  -webkit-mask-image:radial-gradient(75% 70% at 50% 46%, #000 25%, transparent 100%);
  mask-image:radial-gradient(75% 70% at 50% 46%, #000 25%, transparent 100%);
}
.auth-layout{ position:relative; width:100%; max-width:460px; min-width:0; }
/* single-column: the hero's safe-zone corner brackets sit just outside the card (≥ 600; the split layout draws
   them around its visual instead) */
@media (min-width:600px){
  .auth-layout::before{ content:""; position:absolute; inset:-16px; pointer-events:none; }
}
.auth-layout::before, .auth-visual__frame{
  background-image:
    linear-gradient(var(--brackets-c),var(--brackets-c)), linear-gradient(var(--brackets-c),var(--brackets-c)),
    linear-gradient(var(--brackets-c),var(--brackets-c)), linear-gradient(var(--brackets-c),var(--brackets-c)),
    linear-gradient(var(--brackets-c),var(--brackets-c)), linear-gradient(var(--brackets-c),var(--brackets-c)),
    linear-gradient(var(--brackets-c),var(--brackets-c)), linear-gradient(var(--brackets-c),var(--brackets-c));
  background-repeat:no-repeat;
  background-size:14px 1px, 1px 14px, 14px 1px, 1px 14px, 14px 1px, 1px 14px, 14px 1px, 1px 14px;
  background-position:left top, left top, right top, right top, left bottom, left bottom, right bottom, right bottom;
}

/* ── card: the landing's contact panel (glass gradient + cyan top hairline) with a real backdrop blur ── */
.auth-card{ -webkit-backdrop-filter:var(--glass-filter); backdrop-filter:var(--glass-filter); }
.auth-card .v-auth__head{ margin-bottom:28px; }
.auth-card .v-eyebrow{ margin-bottom:16px; }
.auth-card .v-auth__sub{ max-width:38ch; text-wrap:pretty; }
.auth-card form{ margin:0; }
.auth-submit{ margin-top:4px; }
/* the footer row of links (forgot / sign up / back to login) sits under a hairline */
.auth-card .v-auth__foot{ margin-top:24px; padding-top:20px; border-top:1px solid var(--line); }
.auth-card .v-auth__foot > *{ min-width:0; }
/* the links sit in --text-3 text ("New to AdRefresh? Sign up"); link blue vs that grey is only 1.32:1, so colour alone
   cannot mark them (WCAG 1.4.1): underline at rest, like the terms links, full-strength on hover */
.auth-card .v-auth__foot a{
  text-decoration:underline; text-decoration-color:color-mix(in srgb, currentColor 45%, transparent);
  text-decoration-thickness:1px; text-underline-offset:3px;
}
.auth-card .v-auth__foot a:hover{ text-decoration-color:currentColor; }

/* status tile for the message-only states (email sent, password set, invalid links) */
.auth-icon{
  display:grid; place-items:center; width:52px; height:52px; margin:0 0 22px; border-radius:16px;
  color:var(--cyan-text); background:var(--tone-accent-bg); box-shadow:inset 0 0 0 1px var(--tone-accent-line);
}
.auth-icon svg{ width:24px; height:24px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
.auth-icon--success{ color:var(--success); background:var(--tone-success-bg); box-shadow:inset 0 0 0 1px var(--tone-success-line); }
.auth-icon--warning{ color:var(--warning); background:var(--tone-warning-bg); box-shadow:inset 0 0 0 1px var(--tone-warning-line); }
.auth-actions{ display:grid; grid-template-columns:minmax(0, 1fr); gap:10px; }
/* a long label ("Request a new password reset →" at 320 px) wraps, balanced, inside the pill instead of running past
   the card; one-line labels are unchanged (the 10 px block padding fits inside the 48/52 px min-height) */
.auth-card .v-btn{ white-space:normal; text-wrap:balance; padding-top:10px; padding-bottom:10px; }
/* narrow phones (360–399) keep that label on one line: 18 px side padding instead of 26 */
@media (max-width:399px){ .auth-card .v-btn--lg{ padding-left:18px; padding-right:18px; } }
/* label + arrow in one wrapper: when it wraps (320), both lines centre and the arrow stays after the last word */
.auth-btn-label .v-btn__arrow{ margin-left:4px; }
.auth-note{ margin:0 0 24px; color:var(--text-2); font-size:15px; line-height:1.6; text-wrap:pretty; }

/* ── fields (crispy output is styled by app.css; only the auth-specific bits here) ── */
/* password rule lists (signup password1, reset new_password1): a compact list with cyan ticks, not browser discs */
.auth-card .form-text ul{ display:grid; gap:4px; margin:8px 0 0; padding:0; list-style:none; }
.auth-card .form-text li{ position:relative; margin:0; padding-left:15px; }
.auth-card .form-text li::before{
  content:""; position:absolute; left:2px; top:.62em; width:5px; height:5px; border-radius:50%;
  background:color-mix(in srgb, var(--cyan) 70%, transparent);
}
/* crispy renders each field error as its own <p class="invalid-feedback">: no paragraph gap between them */
.auth-card .invalid-feedback{ margin:6px 0 0; }
.auth-card .invalid-feedback + .invalid-feedback{ margin-top:3px; }
/* once a field shows its errors (signup password1 lists the failing rules in red), the grey rule list under it only
   repeats them: hide it until the field is valid again (auth.js stops pointing aria-describedby at it too) */
.auth-card .is-invalid ~ .form-text{ display:none; }
/* signup: the confirm-password hint repeats the obvious (was hidden by users.css; keep it hidden) */
#signup_form #hint_id_password2{ display:none; }
/* terms consent: a bigger, aligned checkbox; links in the label are underlined so they read as links (WCAG 1.4.1) */
.auth-card .form-check{ padding-left:30px; }
.auth-card .form-check-input{ width:18px; height:18px; margin-top:2px; margin-left:-30px; cursor:pointer; }
.auth-card .form-check-label{ font-size:14.5px; line-height:1.45; color:var(--text-2); cursor:pointer; }
.auth-card .form-check-label a{ text-decoration:underline; text-decoration-color:color-mix(in srgb, currentColor 45%, transparent); text-underline-offset:3px; }
.auth-card .form-check-label a:hover{ text-decoration-color:currentColor; }
/* login: the non-field error ("Invalid email/password combination.") sits above the fields */
.auth-card .alert-block{ margin-bottom:22px; }
/* password reset form: the raw {{ form.email }} widget has no class; .v-form styles it, this marks the error state */
.auth-field--invalid input{ border-color:var(--danger); }
.auth-field--invalid input:focus{ border-color:var(--danger); box-shadow:var(--ring-danger); }
.auth-card .v-form input{ max-width:none; }
.auth-card .error-message{ margin-top:7px; }

/* the header hides its own Log in / Sign up link on these pages (url_name check); the 2019 class hooks stay honoured */
.auth-page--login .hide-login, .auth-page--signup .hide-signup{ display:none; }

/* ── split layout (login, signup ≥ 1080): card left, a still of the landing hero right ── */
.auth-visual{ display:none; }
@media (min-width:1080px){
  .auth-stage--split .auth-layout{
    display:grid; grid-template-columns:minmax(0, 460px) minmax(0, 1fr); align-items:center;
    gap:clamp(56px, 6vw, 112px); max-width:calc(var(--maxw) - 2 * var(--gutter));   /* = the nav's .v-wrap content box */
  }
  .auth-stage--split{ --auth-glow-at:74% 48%; }
  .auth-stage--split .auth-layout::before{ content:none; }
  .auth-stage--split .auth-card{ max-width:none; }
  .auth-visual{ display:flex; flex-direction:column; gap:14px; min-width:0; max-width:660px; justify-self:end; width:100%; }
}
/* the hero's telemetry line over the frame */
.auth-visual__labels{
  display:flex; flex-wrap:wrap; justify-content:space-between; gap:4px 16px;
  font:500 10px/1.2 var(--font-mono); letter-spacing:.06em; text-transform:uppercase; color:var(--text-3);
}
.auth-visual__src::before{
  content:""; display:inline-block; width:5px; height:5px; margin:0 8px 1px 0; border-radius:50%;
  background:var(--cyan); box-shadow:0 0 8px var(--cyan); vertical-align:middle;
}
/* safe-zone corner brackets (the hero frame motif) around the poster */
.auth-visual__frame{ position:relative; aspect-ratio:1280 / 1032; padding:5% 4%; }
/* the landing hero's own static poster (home/v28/hero-poster.webp); a CSS background inside the ≥1080 query, so
   phones and tablets never download it */
@media (min-width:1080px){
  .auth-visual__art{
    width:100%; height:100%;
    background:url("../hero-poster.webp") center / contain no-repeat;
  }
}
.auth-visual__note{ margin:0; font:500 11px/1.4 var(--font-mono); letter-spacing:.01em; color:var(--text-3); }

/* phones: the card keeps its glass but tightens; the stage glow moves up behind it */
@media (max-width:599px){
  .auth-stage{ background:
    radial-gradient(70% 40% at 60% 30%, color-mix(in srgb, var(--blue) 14%, transparent), transparent 72%),
    var(--bg); }
  .auth-card.v-panel--lg{ padding:24px 20px; border-radius:var(--r-lg); }
  .auth-card .v-auth__head{ margin-bottom:22px; }
}
