/* ════════════════════════════════════════════════════════════════════
   FADELESS — auth screens (login, signup, forgot, reset, verify)

   A two-panel card floating on the near-black page: showcase artwork on
   the left, the form on the right. Below 860px the artwork drops away
   entirely — on a phone it is decoration competing with the keyboard,
   and a login should be one clean column.

   Loaded after style.css, so every token and the .btn family come from
   there and this stays additive.
   ════════════════════════════════════════════════════════════════════ */

body.auth {
  background: var(--bg);
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: clamp(14px, 4vw, 40px);
}
body.auth .bg-glow {
  background:
    radial-gradient(46% 40% at 22% 8%, rgba(124,155,255,.16), transparent 70%),
    radial-gradient(40% 34% at 84% 92%, rgba(124,155,255,.07), transparent 72%);
}

/* ── the card ───────────────────────────────────────────────────── */
.auth-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  width: min(1000px, 100%);
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 26px;
  padding: 12px;                       /* the frame the artwork sits in */
  gap: clamp(20px, 3vw, 44px);
  box-shadow: 0 40px 110px -40px rgba(0,0,0,.9);
}

/* ── left: artwork ──────────────────────────────────────────────── */
.auth-art {
  position: relative;
  border-radius: 18px;
  overflow: hidden;
  min-height: 496px;
  display: flex;
  flex-direction: column;
  isolation: isolate;                  /* keeps the slides under the text */
}
.auth-art .slide {
  position: absolute; inset: 0; z-index: 0;
  opacity: 0; transition: opacity 1.1s var(--ease);
}
.auth-art .slide.on { opacity: 1; }
.auth-art .slide img { width: 100%; height: 100%; object-fit: cover; }
/* one wash so any photograph still reads as ours, plus a foot gradient
   so the tagline never fights a bright frame */
.auth-art::after {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(10,10,15,.34) 0%, transparent 30%, rgba(10,10,15,.9) 100%),
    linear-gradient(180deg, rgba(60,80,170,.20), rgba(10,10,15,.28));
}

.auth-art-top {
  position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 24px;
}
.auth-art .logo { color: #fff; font-size: 17px; }

.auth-art-foot {
  position: relative; z-index: 2;
  margin-top: auto;
  padding: 0 28px 26px;
}
.auth-art-foot h2 {
  font-size: clamp(24px, 2.4vw, 30px);
  font-weight: 650; letter-spacing: -.03em; line-height: 1.18;
  color: #fff; text-wrap: balance;
}
.auth-art-foot h2 em {
  font-style: normal;
  background: linear-gradient(96deg, #DCE5FF 0%, #9DB4FF 92%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.auth-art-foot p {
  font-size: 13.5px; color: rgba(237,239,247,.72);
  margin-top: 9px; max-width: 34ch; line-height: 1.55;
}

/* carousel dots: the active one stretches into a bar */
.auth-dots { display: flex; gap: 7px; margin-top: 18px; }
.auth-dots button {
  width: 22px; height: 4px; border-radius: 999px;
  background: rgba(250,250,249,.28);
  transition: width .35s var(--ease), background-color .35s var(--ease);
}
.auth-dots button.on { width: 40px; background: #FAFAF9; }

/* ── right: the form ────────────────────────────────────────────── */
.auth-panel {
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(24px, 2.8vw, 38px) clamp(20px, 2.6vw, 34px);
}
.auth-panel h1 {
  font-size: clamp(26px, 2.9vw, 34px);
  font-weight: 650; letter-spacing: -.035em; line-height: 1.1;
}
.auth-sub { font-size: 13.5px; color: var(--text-3); margin-top: 8px; }
.auth-sub .lnk { font-weight: 600; }

/* ── form fields ─────────────────────────────────────────────────────
   --gap-field is the one number that sets the rhythm between questions.
   Tighter than the studio's --sp-3 because a login card is a short,
   focused form: the same spacing that reads as calm on a settings page
   reads as sparse here. */
.auth-form { --gap-field: 19px; margin-top: 20px; }
.auth-form .f-label { display: block; font-size: 12.5px; font-weight: 600; margin: var(--gap-field) 0 7px; }
/* :first-of-type, NOT :first-child — csrf_field() and the `next` input
   are hidden <input>s that sit ahead of the first label, so :first-child
   never matched and every form carried an extra field-gap up top. */
.auth-form > .f-label:first-of-type { margin-top: 0; }
.auth-form .f-input {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); padding: 13px 15px; font-size: 14.5px;
  transition: border-color .2s var(--ease), background-color .2s var(--ease);
}
.auth-form .f-input::placeholder { color: var(--text-3); }
.auth-form .f-input:hover { border-color: var(--line-2); }
.auth-form .f-input:focus { outline: none; border-color: var(--accent); background: var(--surface-2); }
.auth-form .f-input.attn { border-color: rgba(248,113,113,.6); }

/* first and last name share a row */
.f-two { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.f-label-row {
  display: flex; align-items: baseline; justify-content: space-between;
  margin: var(--gap-field, 19px) 0 7px;
}
.f-label-row .f-label { margin: 0; }
.lnk { color: var(--accent-2); text-decoration: none; font-size: 13px; }
.lnk:hover { text-decoration: underline; }

.pw-wrap { position: relative; }
.pw-wrap .f-input { padding-right: 46px; }
.pw-eye {
  position: absolute; right: 7px; top: 50%; translate: 0 -50%;
  width: 32px; height: 32px; display: grid; place-items: center;
  color: var(--text-3); border-radius: 8px;
  transition: color .18s var(--ease);
}
.pw-eye:hover { color: var(--text-2); }
.pw-eye.on { color: var(--accent-2); }
.pw-eye svg { width: 17px; height: 17px; }

.pw-meter { height: 3px; border-radius: 999px; background: var(--surface-2); margin-top: 9px; overflow: hidden; }
.pw-meter i { display: block; height: 100%; width: 0; border-radius: 999px;
              background: var(--text-3); transition: width .25s var(--ease), background-color .25s var(--ease); }
.pw-meter i.weak { background: var(--err); }
.pw-meter i.ok   { background: var(--warn); }
.pw-meter i.good { background: var(--ok); }
.auth-form .f-help { font-size: 12px; color: var(--text-3); margin-top: 6px; }

/* checkbox with a real tick, matching the wizard's pick rows */
.f-check {
  display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  font-size: 13px; color: var(--text-2); margin-top: 17px; line-height: 1.5;
}
.f-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.f-check .box {
  width: 19px; height: 19px; border-radius: 6px; flex: none; margin-top: 1px;
  border: 1.5px solid var(--line-2);
  transition: background-color .18s var(--ease), border-color .18s var(--ease);
}
.f-check input:checked + .box {
  border-color: var(--accent);
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 13 4 4 10-11'/%3E%3C/svg%3E") center/11px no-repeat;
}
.f-check input:focus-visible + .box { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Full width, but NOT .btn.lg: at this width the large size reads as a
   slab rather than a button. */
.auth-go {
  width: 100%; margin-top: 20px; justify-content: center;
  padding: 12px 22px; font-size: 14.5px;
}
.auth-fine { font-size: 11.5px; color: var(--text-3); line-height: 1.55; margin-top: 12px; }

/* ── messages ───────────────────────────────────────────────────── */
.auth-alert {
  display: flex; align-items: flex-start; gap: 10px;
  border-radius: var(--r-sm); padding: 11px 13px; margin-top: 18px;
  font-size: 13px; line-height: 1.5;
}
.auth-alert svg { width: 16px; height: 16px; flex: none; margin-top: 1px; }
.auth-alert.err  { background: rgba(248,113,113,.09); border: 1px solid rgba(248,113,113,.32); color: #F5A9A9; }
.auth-alert.ok   { background: rgba(74,222,128,.09);  border: 1px solid rgba(74,222,128,.32);  color: #A7EFC3; }
.auth-alert.info { background: var(--accent-soft);    border: 1px solid rgba(124,155,255,.3);  color: var(--accent-2); }
.auth-alert a { color: inherit; font-weight: 600; }

/* Inside a form the message sits directly above the submit button, so
   it is read as the reason that button did not work. Proximity has to
   say so: a wider gap above than below groups it with the button
   rather than with the field it happens to follow. Margins collapse in
   this normal-flow form, so these are the gaps you actually get. */
.auth-form .auth-alert { margin-top: 22px; }
.auth-form .auth-alert + .auth-go { margin-top: 16px; }

/* ── divider + social ───────────────────────────────────────────── */
.auth-or {
  display: flex; align-items: center; gap: 12px;
  margin: 18px 0 12px; color: var(--text-3); font-size: 12px;
}
.auth-or::before, .auth-or::after { content: ''; flex: 1; height: 1px; background: var(--line); }
/* ── social sign-in ─────────────────────────────────────────────────
   Our own button carries the design; Google's real one is rendered
   underneath at zero height and clicked programmatically, because GIS
   will not hand us a token from an arbitrary element. */
.social-row { position: relative; display: grid; gap: 9px; }
/* 11px + a 1px border matches the primary button's 12px and no border,
   so the two stack at exactly the same height */
.btn.social {
  width: 100%; justify-content: center; gap: 10px;
  padding: 11px 22px; font-size: 14.5px; font-weight: 600;
  border: 1px solid var(--line-2); background: var(--surface); color: var(--text);
}
.btn.social:hover { background: var(--surface-2); border-color: rgba(183,190,215,.6); }
.btn.social svg { width: 18px; height: 18px; flex: none; }
.g-real {
  position: absolute; inset: 0; z-index: -1;
  opacity: 0; pointer-events: none; overflow: hidden;
}

.auth-foot { font-size: 13.5px; color: var(--text-3); margin-top: 18px; }

/* ── signing-in animation ────────────────────────────────────────────
   The choreography, in order:
     1. every row of the form lifts away on its own beat, top to bottom
     2. the artwork column closes and the card narrows around it
     3. a ring draws, a tick strokes on, and the card hands off
   Nothing starts until the server has confirmed the credentials, so a
   success animation can never play over a failed login. */
.auth-panel { position: relative; transition: height .55s var(--ease); }

.auth-form.sending { pointer-events: none; }

/* The sign-out cascade and the checkmark are animated by GSAP in
   auth.js, not by CSS transitions. GSAP writes inline styles, which
   beat `.auth-form .f-input`'s own transition declaration — the exact
   specificity clash that made one field snap while its neighbours
   eased back when this was pure CSS. */

/* The card keeps its dimensions throughout: nothing resizes, and the
   artwork is left exactly as it is. Everything happens inside the right
   panel, which is why the panel's height is locked in JS before the
   rows leave — otherwise they would drag the card shut behind them. */
.auth-go .spin {
  width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  display: inline-block; animation: spin .7s linear infinite;
}

/* No background of its own: the form has already left, so the check
   sits on the card itself rather than on a panel covering it. */
.auth-done {
  position: absolute; inset: 0; z-index: 5;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; text-align: center;
  opacity: 0; pointer-events: none;
}
.auth-done p { font-size: 15px; font-weight: 600; color: var(--text); opacity: 0; }

.done-ring { width: 66px; height: 66px; }
.done-ring circle, .done-ring path {
  fill: none; stroke-linecap: round; stroke-linejoin: round;
}
.done-ring circle { stroke: var(--ok); stroke-width: 2.5; opacity: .35;
  stroke-dasharray: 176; stroke-dashoffset: 176; }
.done-ring path   { stroke: var(--ok); stroke-width: 3.4;
  stroke-dasharray: 40;  stroke-dashoffset: 40; }
/* both strokes are drawn by GSAP tweening stroke-dashoffset */

/* the hand-off: the whole card eases up and out */
.auth-card.leaving {
  animation: cardLeave .45s var(--ease) forwards;
}
@keyframes cardLeave {
  to { opacity: 0; transform: translateY(-14px) scale(.985); }
}

@media (prefers-reduced-motion: reduce) {
  .auth-done, .auth-done p { transition: none; }
  .auth-done.on .done-ring circle,
  .auth-done.on .done-ring path { animation: none; stroke-dashoffset: 0; }
  .auth-card.leaving { animation: none; opacity: 0; }
}

/* Shown only once the artwork panel is gone, so the brand still leads
   the page on a phone. Declared BEFORE the media query that reveals it:
   both rules have equal specificity, so whichever comes last wins. */
.auth-panel .auth-logo {
  display: none;
  align-items: center; gap: 10px;
  font-size: 16px; font-weight: 600; text-decoration: none;
  margin-bottom: var(--sp-3);
}

/* ── responsive ─────────────────────────────────────────────────────
   Under 860px the artwork is dropped rather than stacked: on a phone it
   would push the form below the fold behind the keyboard. */
@media (max-width: 860px) {
  .auth-card {
    grid-template-columns: minmax(0, 1fr);
    width: min(440px, 100%);
    padding: 0; gap: 0;
    border-radius: var(--r-lg);
  }
  .auth-art { display: none; }
  .auth-panel { padding: clamp(24px, 6vw, 34px); }
  .auth-panel .auth-logo { display: flex; }
}

@media (max-width: 420px) {
  .f-two { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .auth-art .slide, .auth-dots button { transition: none; }
}


/* ── sign in with a passkey ─────────────────────────────────────────
   Below the password button, above the Google divider: it is an
   alternative to typing a password, not a social login. Hidden until
   JS confirms the browser supports WebAuthn. */
.pk-signin { margin-top: 10px; }
.pk-signin .btn { width: 100%; justify-content: center; gap: 9px; }
.pk-signin svg { width: 17px; height: 17px; }
