/* ---------------------------------------------------------------------
   Machina login — the one dark screen in the app.

   Loaded only by templates/registration/login.html (via extra_head), so
   none of this weight lands on the ten stage pages. The composition is
   the loop itself: the wordmark ring from the loop bar, blown up, with a
   node for each of the ten stages and a pulse travelling round them.
   Everything animates in CSS; there is no JS on this page.
   --------------------------------------------------------------------- */

.login-page {
  --lg-bg: #0a0b0f;
  --lg-bg-2: #12131b;
  --lg-accent: #7c74e8;
  --lg-accent-dim: #534ab7;
  --lg-accent-glow: rgba(124, 116, 232, 0.55);
  --lg-text: #e8e9f2;
  --lg-muted: #8b8fa6;
  --lg-faint: #5a5e73;
  --lg-line: rgba(255, 255, 255, 0.09);
  --lg-field: rgba(255, 255, 255, 0.035);

  min-height: 100vh;
  min-height: 100dvh;
  background: var(--lg-bg);
  color: var(--lg-text);
  color-scheme: dark;
  overflow-x: hidden;
}

/* The page wrapper from base.html is padded and width-capped for stage
   screens; the login screen is full bleed instead. */
.login-page main.page {
  padding: 0;
  max-width: none;
  margin: 0;
}

/* --- Atmosphere ---------------------------------------------------- */

.login-shell {
  position: relative;
  isolation: isolate;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--sp-5);
}

/* Two slow-drifting colour fields + a vignette. */
.login-shell::before {
  content: "";
  position: absolute;
  inset: -20%;
  z-index: -3;
  background:
    radial-gradient(38% 38% at 30% 32%, rgba(83, 74, 183, 0.42), transparent 70%),
    radial-gradient(32% 32% at 72% 68%, rgba(46, 122, 160, 0.28), transparent 70%),
    radial-gradient(60% 60% at 50% 50%, var(--lg-bg-2), var(--lg-bg) 72%);
  filter: blur(10px);
  animation: lg-drift 34s ease-in-out infinite alternate;
}

/* Fine dot grid, faded out towards the edges. */
.login-shell::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: radial-gradient(rgba(255, 255, 255, 0.16) 1px, transparent 1px);
  background-size: 34px 34px;
  opacity: 0.5;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 45%, #000, transparent 100%);
  mask-image: radial-gradient(70% 60% at 50% 45%, #000, transparent 100%);
}

/* Film grain — keeps the flat gradients from banding. */
.login-grain {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

@keyframes lg-drift {
  from { transform: translate3d(-2%, -1%, 0) scale(1); }
  to   { transform: translate3d(3%, 2%, 0) scale(1.08); }
}

/* --- Layout -------------------------------------------------------- */

.login-layout {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  justify-items: center;
  gap: var(--sp-6);
  width: 100%;
  max-width: 940px;
}

@media (min-width: 900px) {
  .login-layout {
    grid-template-columns: minmax(0, 1fr) 340px;
    align-items: center;
    justify-items: stretch;
    gap: 64px;
  }
}

/* --- The mark ------------------------------------------------------ */

.login-mark {
  display: grid;
  justify-items: center;
  gap: var(--sp-4);
  animation: lg-rise 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

.login-ring {
  width: min(300px, 62vw);
  height: auto;
  overflow: visible;
  filter: drop-shadow(0 0 34px rgba(83, 74, 183, 0.45));
}

.lr-halo {
  fill: url(#lg-halo);
}
.lr-orbit {
  fill: none;
  stroke: rgba(255, 255, 255, 0.10);
  stroke-width: 1;
  stroke-dasharray: 3 9;
  transform-origin: 160px 160px;
  animation: lg-spin 90s linear infinite;
}
.lr-orbit-inner {
  fill: none;
  stroke: rgba(255, 255, 255, 0.06);
  stroke-width: 1;
  stroke-dasharray: 1 7;
  transform-origin: 160px 160px;
  animation: lg-spin 60s linear infinite reverse;
}
.lr-track {
  fill: none;
  stroke: rgba(255, 255, 255, 0.13);
  stroke-width: 5;
}

/* The two arcs of the wordmark ring, drawn in on load. */
.lr-arc {
  fill: none;
  stroke: url(#lg-arc);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: lg-sweep 2.2s cubic-bezier(0.22, 0.61, 0.36, 1) 0.25s both;
}
.lr-arc-b {
  animation-delay: 0.45s;
}

/* Comet. Four dash segments on the same circle, offset so they all END at
   the same point: the shortest is the bright head, the longer, fainter ones
   trail behind it. Rotating the set together reads as clockwise travel —
   which is what an arrowhead used to be doing, badly. Circumference at
   r=104 is ~653.5, so each dash + gap pair sums to that. */
.lr-comet {
  fill: none;
  stroke: var(--lg-accent);
  stroke-linecap: round;
  transform-origin: 160px 160px;
  opacity: 0;
  animation:
    lg-spin 6s linear 2.2s infinite,
    lg-fade-in 1.2s ease-out 2.2s both;
}
.lr-comet-1 {
  stroke-width: 5;
  stroke-dasharray: 12 641.5;
  stroke-dashoffset: -78;
  filter: drop-shadow(0 0 9px var(--lg-accent-glow));
}
.lr-comet-2 {
  stroke-width: 5;
  stroke-dasharray: 30 623.5;
  stroke-dashoffset: -60;
  stroke-opacity: 0.4;
}
.lr-comet-3 {
  stroke-width: 4.5;
  stroke-dasharray: 56 597.5;
  stroke-dashoffset: -34;
  stroke-opacity: 0.2;
}
.lr-comet-4 {
  stroke-width: 4;
  stroke-dasharray: 90 563.5;
  stroke-opacity: 0.1;
}

/* Ten nodes, one per loop stage, lit in sequence for ever. */
.lr-node {
  fill: var(--lg-bg);
  stroke: rgba(255, 255, 255, 0.28);
  stroke-width: 2;
  opacity: 0;
  /* Scale rather than animate the `r` attribute — Safari does not animate
     SVG geometry properties from CSS. */
  transform-box: fill-box;
  transform-origin: center;
  animation:
    lg-node-in 0.5s ease-out both,
    lg-node-pulse 4s ease-in-out infinite;
}
.lr-node-0 { animation-delay: 1.20s, 2.40s; }
.lr-node-1 { animation-delay: 1.28s, 2.48s; }
.lr-node-2 { animation-delay: 1.36s, 2.56s; }
.lr-node-3 { animation-delay: 1.44s, 2.64s; }
.lr-node-4 { animation-delay: 1.52s, 2.72s; }
.lr-node-5 { animation-delay: 1.60s, 2.80s; }
.lr-node-6 { animation-delay: 1.68s, 2.88s; }
.lr-node-7 { animation-delay: 1.76s, 2.96s; }
.lr-node-8 { animation-delay: 1.84s, 3.04s; }
.lr-node-9 { animation-delay: 1.92s, 3.12s; }

@keyframes lg-sweep {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}
@keyframes lg-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@keyframes lg-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes lg-node-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes lg-node-pulse {
  0%, 72%, 100% {
    fill: var(--lg-bg);
    stroke: rgba(255, 255, 255, 0.28);
    transform: scale(1);
  }
  80% {
    fill: var(--lg-accent);
    stroke: var(--lg-accent);
    transform: scale(1.5);
  }
}

/* --- Wordmark and stage ticker ------------------------------------- */

.login-word {
  margin: 0;
  font-size: 30px;
  font-weight: 600;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  color: var(--lg-text);
  animation: lg-rise 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) 1.9s both;
}

.login-tagline {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--lg-muted);
  text-align: center;
  animation: lg-rise 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) 2.1s both;
}

/* The ten stage names, cycling in place — one full pass of the loop
   every 30s, so the screen tells you what the app is while you type. */
.login-ticker {
  position: relative;
  height: 16px;
  width: 220px;
  margin-top: var(--sp-1);
}
.login-ticker span {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--lg-accent);
  opacity: 0;
  animation: lg-ticker 30s linear infinite;
}
.login-ticker span:nth-child(1)  { animation-delay: 0s; }
.login-ticker span:nth-child(2)  { animation-delay: 3s; }
.login-ticker span:nth-child(3)  { animation-delay: 6s; }
.login-ticker span:nth-child(4)  { animation-delay: 9s; }
.login-ticker span:nth-child(5)  { animation-delay: 12s; }
.login-ticker span:nth-child(6)  { animation-delay: 15s; }
.login-ticker span:nth-child(7)  { animation-delay: 18s; }
.login-ticker span:nth-child(8)  { animation-delay: 21s; }
.login-ticker span:nth-child(9)  { animation-delay: 24s; }
.login-ticker span:nth-child(10) { animation-delay: 27s; }

@keyframes lg-ticker {
  0%   { opacity: 0; transform: translateY(4px); }
  2%   { opacity: 1; transform: translateY(0); }
  9%   { opacity: 1; transform: translateY(0); }
  11%  { opacity: 0; transform: translateY(-4px); }
  100% { opacity: 0; transform: translateY(-4px); }
}

@keyframes lg-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* --- The card ------------------------------------------------------ */

.login-card {
  width: 100%;
  max-width: 340px;
  justify-self: center;
  padding: var(--sp-5);
  border: 1px solid var(--lg-line);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.045);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  box-shadow:
    0 24px 60px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
  animation: lg-rise 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) 0.35s both;
}

/* Set like the wordmark under the ring, so the card echoes the mark
   rather than introducing a third voice. */
.login-card h2 {
  margin: 0 0 var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--lg-line);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  text-transform: uppercase;
  text-align: center;
  color: var(--lg-text);
}
.login-google-form {
  margin: 0;
}

.login-google {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  width: 100%;
  padding: 11px var(--sp-3);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--lg-text);
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid var(--lg-line);
  border-radius: var(--radius-md);
  cursor: pointer;
  overflow: hidden;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.12s ease;
}
.login-google:hover {
  background: rgba(255, 255, 255, 0.095);
  border-color: rgba(255, 255, 255, 0.2);
}
.login-google:active {
  transform: translateY(1px);
}
.login-google:focus-visible {
  outline: 2px solid var(--lg-accent);
  outline-offset: 2px;
}
/* Light sweeping across the button on hover. */
.login-google::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.16), transparent);
  transform: skewX(-20deg);
  transition: left 0.55s ease;
}
.login-google:hover::after {
  left: 120%;
}

/* Google's mark keeps its own colours — brand requirement, and the one
   colour accent that earns its place on a dark screen. */
.login-google-g {
  flex: 0 0 auto;
  display: block;
}

.login-errors {
  margin: 0 0 var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  font-size: 12px;
  color: #ffb4a2;
  background: rgba(179, 69, 47, 0.18);
  border: 1px solid rgba(179, 69, 47, 0.5);
  border-radius: var(--radius-md);
}
.login-errors p {
  margin: 0;
}

/* Body copy on the standalone allauth pages (provider confirmation and
   auth error). Those render a lone .login-card inside .login-shell, which
   is `place-items: center`, so they need no layout wrapper of their own. */
.login-note {
  margin: 0 0 var(--sp-4);
  font-size: 12px;
  line-height: 1.5;
  color: var(--lg-muted);
  text-align: center;
}

.login-foot {
  margin: var(--sp-4) 0 0;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--lg-line);
  font-size: 11px;
  color: var(--lg-faint);
  text-align: center;
}
/* machina.css links are the light-theme purple, unreadable on this ground. */
.login-foot a {
  color: var(--lg-accent);
}

/* --- Reduced motion: keep the composition, drop the movement ------- */

@media (prefers-reduced-motion: reduce) {
  .login-shell::before,
  .login-mark,
  .login-word,
  .login-tagline,
  .login-card,
  .lr-orbit,
  .lr-orbit-inner,
  .lr-arc,
  .lr-node,
  .lr-comet,
  .login-ticker span {
    animation: none;
  }
  .lr-arc { stroke-dashoffset: 0; }
  .lr-node,
  .login-mark,
  .login-word,
  .login-tagline,
  .login-card { opacity: 1; transform: none; }
  .lr-comet { opacity: 0; }
  /* Without the cycle, show only the first stage name. */
  .login-ticker span { opacity: 0; }
  .login-ticker span:first-child { opacity: 1; }
  .login-google::after { display: none; }
}
