/* ===========================================================================
   Northwest Falls: login / register / setup
   ---------------------------------------------------------------------------
   Split layout: form on the left, atmosphere on the right. On mobile the
   atmosphere is dropped entirely. A decorative panel that pushes the form
   below the fold is worse than no panel.
   =========================================================================== */

body { min-height: 100vh; min-height: 100dvh; }

.auth {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 100vh;
  min-height: 100dvh;
}

/* --- Form side ------------------------------------------------------------ */

.auth__form-side {
  display: flex;
  flex-direction: column;
  padding: var(--space-8);
  overflow-y: auto;
}

.auth__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  align-self: flex-start;
}
.auth__brand img { width: 28px; height: 28px; object-fit: contain; }
.auth__brand span { font-size: var(--text-md); font-weight: 600; letter-spacing: -0.025em; }

.auth__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  max-width: 380px;
  width: 100%;
  margin-inline: auto;
  padding-block: var(--space-12);
}

.auth__title { font-size: var(--text-2xl); letter-spacing: -0.03em; }
.auth__lede  { font-size: var(--text-sm); color: var(--text-tertiary); margin-top: var(--space-2); }

.auth__form { display: flex; flex-direction: column; gap: var(--space-4); margin-top: var(--space-8); }

.auth__alt {
  margin-top: var(--space-6);
  font-size: var(--text-sm);
  color: var(--text-tertiary);
  text-align: center;
}
.auth__alt a { color: var(--text-primary); font-weight: 500; text-decoration: underline; text-underline-offset: 3px; }
.auth__alt a:hover { color: var(--text-secondary); }

.auth__legal {
  margin-top: var(--space-6);
  font-size: var(--text-xs);
  color: var(--text-quaternary);
  line-height: 1.55;
  text-align: center;
}
.auth__legal a { color: var(--text-tertiary); text-decoration: underline; }
.auth__legal a:hover { color: var(--text-secondary); }

.auth__foot {
  display: flex;
  gap: var(--space-4);
  justify-content: center;
  font-size: var(--text-xs);
  color: var(--text-quaternary);
}
.auth__foot a:hover { color: var(--text-secondary); }

/* Inline error banner: errors belong next to the form, not in a toast that
   disappears while the user is still reading it. */
.auth__error {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 32%, transparent);
  font-size: var(--text-sm);
  color: var(--danger);
  line-height: 1.5;
  animation: nw-fade-up var(--dur-med) var(--ease-out);
}
.auth__error i { margin-top: 3px; flex: none; }

.auth__success {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  animation: nw-fade-up var(--dur-slow) var(--ease-out);
}
.auth__success-icon {
  width: 56px; height: 56px;
  display: grid; place-items: center;
  border-radius: var(--radius-lg);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 22px;
}

/* --- Password strength ---------------------------------------------------- */

.strength { display: flex; gap: 4px; margin-top: var(--space-2); }
.strength__seg {
  flex: 1;
  height: 3px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  transition: background var(--dur-med) var(--ease-out);
}
.strength[data-level="1"] .strength__seg:nth-child(-n+1),
.strength[data-level="2"] .strength__seg:nth-child(-n+2) { background: var(--danger); }
.strength[data-level="3"] .strength__seg:nth-child(-n+3) { background: var(--warning); }
.strength[data-level="4"] .strength__seg { background: var(--success); }

/* --- Handle availability -------------------------------------------------- */

.handle-field { position: relative; }
.handle-field .input { padding-left: 30px; padding-right: 38px; }
.handle-field__at {
  position: absolute;
  left: 12px; top: 50%;
  transform: translateY(-50%);
  color: var(--text-quaternary);
  font-size: var(--text-base);
  pointer-events: none;
}
.handle-field__state {
  position: absolute;
  right: 12px; top: 50%;
  transform: translateY(-50%);
  font-size: 13px;
}
.handle-field__state[data-state="checking"] { color: var(--text-quaternary); }
.handle-field__state[data-state="free"]     { color: var(--success); }
.handle-field__state[data-state="taken"]    { color: var(--danger); }

/* --- Atmosphere side ------------------------------------------------------
   Photographs, not a synthetic gradient. The one warm thing in an otherwise
   monochrome product.

   They are real <img> elements rather than background-images so the first can
   carry fetchpriority, so the browser has an intrinsic size to reserve, and so
   backdrop.js can attach the rest one at a time instead of firing nine
   requests alongside the API call the user is waiting on.

   Timing comes from backdrop.js, which sets --nw-fade and --nw-drift on this
   element. The values below are fallbacks for the case where the script never
   runs, so the panel still dissolves rather than cutting. Change the pace
   there, not here.
   --------------------------------------------------------------------------- */

.auth__art {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--space-12);
  overflow: hidden;
  background: var(--bg-deep);
  border-left: 1px solid var(--border-subtle);
}

.auth__slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transform: scale(1.02);
  /* Linear, not eased. An eased crossfade dips in the middle, because both
     layers are near half opacity at the same moment and the result reads as a
     flicker rather than a dissolve. */
  transition: opacity var(--nw-fade, 2200ms) linear;
}

.auth__slide.is-active {
  opacity: 1;
  animation: nw-drift var(--nw-drift, 10s) linear forwards;
}

/* A slow push in. Small enough that nobody consciously notices it moving, big
   enough that a still photograph does not feel like a stuck page. */
@keyframes nw-drift {
  from { transform: scale(1.02); }
  to   { transform: scale(1.09); }
}

/* Bottom-weighted scrim. It has to hold white text over nine different
   photographs, several of which are bright skies, so it is heavier than a
   single dark image would need. */
.auth__art::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.88) 0%,
    rgba(0, 0, 0, 0.58) 30%,
    rgba(0, 0, 0, 0.22) 62%,
    rgba(0, 0, 0, 0.36) 100%
  );
}

/* These two are deliberately literal rather than tokens. The text sits on a
   photograph, which does not change with the theme, so a token that flips to
   near-black in light mode would make this unreadable exactly half the time. */
.auth__quote { position: relative; z-index: 1; max-width: 420px; }
.auth__quote p {
  font-size: var(--text-xl);
  line-height: 1.5;
  letter-spacing: -0.02em;
  color: #ffffff;
  text-wrap: balance;
}
.auth__quote cite {
  display: block;
  margin-top: var(--space-5);
  font-size: var(--text-sm);
  font-style: normal;
  color: rgba(255, 255, 255, 0.62);
}

/* --- Setup steps ---------------------------------------------------------- */

.steps { display: flex; gap: var(--space-2); margin-bottom: var(--space-8); }
.step {
  flex: 1;
  height: 3px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  transition: background var(--dur-slow) var(--ease-out);
}
.step.is-done, .step.is-current { background: var(--accent); }

.genre-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.genre {
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  border: 1px solid var(--border-subtle);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  transition: all var(--dur-fast) var(--ease-out);
}
.genre:hover { border-color: var(--border-strong); }
.genre[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: var(--accent);
}

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 900px) {
  .auth { grid-template-columns: 1fr; }
  /* Dropped, not stacked: a decorative panel above the form pushes the actual
     task off screen on a phone. */
  .auth__art { display: none; }
  .auth__form-side { padding: var(--space-6); }
}

@media (max-width: 480px) {
  .auth__form-side { padding: var(--space-5); }
  .auth__body { padding-block: var(--space-8); }
  .auth__title { font-size: var(--text-xl); }
}
