/* Login page — wireframe 3b on the ASCII globe.
   Inherits the palette from styles.css; everything here is page-specific. */

.login-body {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; position: relative;
  /* Warm ember wash under the art so the backdrop is not flat black. */
  background:
    radial-gradient(ellipse at 50% 42%, oklch(0.175 0.032 30), var(--bg) 68%);
}

/* ── the grid ──────────────────────────────────────────────────────────── */

/* The board's own 44px grid, carried onto the login page so the two screens
   read as one product. Masked to a soft ellipse so it never reaches the edge. */
.grid-bg {
  position: fixed; inset: -44px; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in oklch, var(--text) 5%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in oklch, var(--text) 5%, transparent) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: radial-gradient(ellipse 62% 66% at 50% 46%, #000 28%, transparent 82%);
  -webkit-mask-image: radial-gradient(ellipse 62% 66% at 50% 46%, #000 28%, transparent 82%);
  animation: grid-drift 26s linear infinite;
}
/* One cell of travel, then it repeats seamlessly. */
@keyframes grid-drift {
  to { background-position: 44px 44px; }
}

/* ── the globe ─────────────────────────────────────────────────────────── */

.ascii-bg {
  position: fixed; inset: 0; margin: 0; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono);
  /* 79 rows x 146 cols — nearly square, so height constrains as often as
     width. Both are capped or the art crops on a short window. */
  font-size: clamp(3px, min(1.02vw, 1.12vh), 15px);
  line-height: 1;
  letter-spacing: 0;
  white-space: pre;
  user-select: none; pointer-events: none;

  /* Red throughout — bright at the top, deepening to oxblood at the base.
     Hue stays in the 22-30 band; past ~40 it reads orange. The solid colour
     is the fallback if background-clip fails. */
  color: oklch(0.64 0.2 27 / 0.66);
  background-image: linear-gradient(
    172deg,
    oklch(0.72 0.21 29 / 0.95) 0%,
    oklch(0.66 0.21 27 / 0.9) 34%,
    oklch(0.58 0.2 25 / 0.86) 68%,
    oklch(0.46 0.16 23 / 0.72) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;

  /* Tight-to-wide: the close shadow sharpens each glyph, the far ones pool
     into a halo. All red, so the glow does not tint the gradient warm. */
  text-shadow:
    0 0 2px oklch(0.74 0.21 28 / 0.5),
    0 0 8px oklch(0.66 0.2 27 / 0.4),
    0 0 20px oklch(0.60 0.19 26 / 0.26),
    0 0 46px oklch(0.56 0.18 25 / 0.14);
  animation: ascii-in 1.6s ease both;
}
@keyframes ascii-in {
  from { opacity: 0; transform: scale(1.04); }
  to { opacity: 1; transform: none; }
}

/* Settles the edges and takes the glare off the middle. Kept light behind the
   card — the globe is meant to show through it, not be blacked out first. */
.ascii-vignette {
  position: fixed; inset: 0; z-index: 2; pointer-events: none;
  background:
    radial-gradient(ellipse 34% 42% at 50% 50%, oklch(0.10 0.003 40 / 0.38), transparent 74%),
    radial-gradient(ellipse at 50% 50%, transparent 46%, oklch(0.10 0.003 40 / 0.7) 90%);
}

/* Scanlines over the whole page, matching the console. */
.login-body::after {
  content: ''; position: fixed; inset: 0; z-index: 3; pointer-events: none;
  background: repeating-linear-gradient(
    to bottom, oklch(1 0 0 / 0.014) 0 1px, transparent 1px 3px);
}

/* ── the card ──────────────────────────────────────────────────────────── */

.login-stage {
  position: relative; z-index: 4;
  display: flex; flex-direction: column; align-items: center; gap: 0;
  animation: login-in 0.5s 0.15s ease both;
}
@keyframes login-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

.login-brand { display: flex; align-items: baseline; gap: 10px; }
.login-brand .brand-mark { font-size: 26px; }
.login-brand .brand-name { font-size: 26px; }
.login-tagline {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--muted); margin: 6px 0 22px;
}

/* 3b: card surface, admin as a small link beneath the primary button.
   Deliberately see-through — the globe should be legible behind the glass.
   `--card-veil` is the one knob: lower shows more animation, higher is calmer. */
.login-card {
  --card-veil: 0.6;

  width: 340px; box-sizing: border-box; padding: 28px;
  background: oklch(0.15 0.006 50 / var(--card-veil));
  border: 1px solid oklch(0.4 0.02 40 / 0.55);
  border-radius: 16px;
  /* Only a touch of blur: enough to stop the ASCII shimmering under the
     labels, not so much that it stops reading as the globe. */
  backdrop-filter: blur(2.5px) saturate(1.1);
  box-shadow:
    0 24px 60px oklch(0 0 0 / 0.55),
    inset 0 1px 0 oklch(1 0 0 / 0.06);
}

.login-title {
  font-family: var(--mono); font-weight: 500; font-size: 22px;
  color: oklch(0.95 0.008 50); margin-bottom: 20px;
}

.ag-label {
  display: block; margin-bottom: 6px;
  font-family: var(--sans); font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.08em; color: oklch(0.68 0.008 50);
}

.ag-input {
  width: 100%; box-sizing: border-box; margin-bottom: 14px;
  /* Held more solid than the card: what you type has to stay readable even
     when the globe is churning underneath. */
  background: oklch(0.21 0.008 50 / 0.86);
  border: 1px solid oklch(0.34 0.01 50);
  border-radius: 8px; padding: 11px 12px;
  font-family: var(--mono); font-size: 13px; color: oklch(0.9 0.008 50);
  outline: none; transition: border-color 0.14s, box-shadow 0.14s;
}
.ag-input::placeholder { color: oklch(0.5 0.01 50); }
.ag-input:focus { border-color: var(--red); box-shadow: 0 0 0 3px var(--red-soft); }
.ag-input:last-of-type { margin-bottom: 20px; }

.login-submit {
  width: 100%; margin-bottom: 12px; padding: 12px;
  background: oklch(0.6 0.19 25); color: oklch(0.98 0.01 25);
  border: none; border-radius: 8px; cursor: pointer;
  font-family: var(--sans); font-weight: 600; font-size: 14px;
  transition: filter 0.14s;
}
.login-submit:hover { filter: brightness(1.1); }
.login-submit:disabled { opacity: 0.55; cursor: progress; }

.login-admin {
  display: block; text-align: center; text-decoration: none;
  font-family: var(--sans); font-size: 12px; color: oklch(0.6 0.19 25);
  transition: filter 0.14s;
}
.login-admin:hover { filter: brightness(1.25); }

.login-error {
  margin-bottom: 14px; padding: 8px 10px; border-radius: 6px;
  border-left: 2px solid var(--red); background: var(--red-soft);
  font-family: var(--mono); font-size: 11px; line-height: 1.45; color: var(--red);
}

.login-foot {
  margin-top: 20px; font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
}

/* Admin mode recolours the card's accent so the state is unmistakable. */
.login-card.is-admin { border-color: oklch(0.76 0.15 75 / 0.55); }
.login-card.is-admin .login-title::after {
  content: ' · admin'; color: var(--amber); font-size: 13px;
}
.login-card.is-admin .login-submit { background: var(--amber); color: oklch(0.18 0.02 75); }
.login-card.is-admin .ag-input:focus {
  border-color: var(--amber); box-shadow: 0 0 0 3px oklch(0.76 0.15 75 / 0.14);
}
.login-card.is-admin .login-admin { color: var(--amber); }

/* ── signing in ────────────────────────────────────────────────────────── */

/* The card lets go first, then the globe travels out to the left — so the eye
   follows the artwork off the page rather than watching the form vanish. */
.login-body.is-leaving .login-stage {
  opacity: 0;
  transform: translateY(8px) scale(0.98);
  transition: opacity 0.34s ease, transform 0.34s ease;
  pointer-events: none;
}

.login-body.is-leaving .ascii-bg {
  /* The intro keyframes would otherwise pin the transform. */
  animation: none;
  opacity: 0;
  transform: translateX(-62vw) scale(0.94);
  transition:
    transform 0.78s cubic-bezier(0.6, 0, 0.3, 1) 0.12s,
    opacity 0.78s ease 0.12s;
}

.login-body.is-leaving .grid-bg {
  animation: none;
  opacity: 0;
  transform: translateX(-14vw);
  transition: transform 0.78s cubic-bezier(0.6, 0, 0.3, 1) 0.12s, opacity 0.6s ease 0.16s;
}

.login-body.is-leaving .ascii-vignette {
  opacity: 0;
  transition: opacity 0.5s ease;
}

@media (prefers-reduced-motion: reduce) {
  .ascii-bg, .login-stage, .grid-bg { animation: none; }
  .login-body.is-leaving .ascii-bg,
  .login-body.is-leaving .grid-bg,
  .login-body.is-leaving .login-stage {
    transition: opacity 0.2s ease;
    transform: none;
  }
}
