/* ---- Login backdrop: the pixel-art scene in /static/img/login/, set in motion ----
   Every layer travels down-left on the same 1:5 slope the artwork's rainbows are
   drawn on, so each cat's trail points back along its own line of flight.
   Sprites are cut from the source art; toasters.js flies them. */

body.toaster-bg { background: #05060f; }

.toaster-sky {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background:
    radial-gradient(105% 80% at 82% 4%,  #180f38 0%, rgba(14,10,42,0) 48%),
    radial-gradient(90% 70% at 6% 98%,   #101235 0%, rgba(10,12,38,0) 52%),
    radial-gradient(150% 130% at 45% 45%, #07081590 0%, #05060f 75%);
}

/* ---- Starfield: two tiles of their own stars, at different speeds ---- */
/* Each cycle shifts 5 tiles left and 1 down - an exact tile multiple both ways,
   so the loop is invisible, and 5:1 is the artwork's slope. The stars stream the
   opposite way to the traffic on purpose: that is what reads as forward flight. */
.stars {
  position: absolute;
  inset: 0;
  background-repeat: repeat;
  image-rendering: pixelated;
}

.stars-far {
  background-image: url(/static/img/login/stars-2.png);
  opacity: .40;
  animation: stars-far 300s linear infinite;
}

.stars-near {
  background-image: url(/static/img/login/stars-1.png);
  opacity: .72;
  animation: stars-near 150s linear infinite;
}

@keyframes stars-far  { to { background-position: -6400px 1280px; } }
@keyframes stars-near { to { background-position: -5120px 1024px; } }

/* ---- Galaxy and planet: far enough off to barely move ---- */
.celestial {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
  image-rendering: pixelated;
  animation-name: drift;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.celestial img { display: block; width: var(--w); height: auto; }

/* ---- Flying sprites ---- */
.sprite {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
  animation-name: drift;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.sprite img,
.hero img {
  display: block;
  width: var(--w);
  height: auto;
  image-rendering: pixelated;   /* keep the pixels crisp at any size */
}

@keyframes drift {
  from { transform: translate3d(var(--x0), var(--y0), 0); }
  to   { transform: translate3d(var(--x1), var(--y1), 0); }
}

/* A little lift and fall - the art is a single frame, so the wings can't flap */
.sprite-toaster img { animation: bob 1.6s ease-in-out infinite; }
@keyframes bob {
  0%, 100% { transform: translateY(-3px); }
  50%      { transform: translateY(3px); }
}

.sprite-toast img { animation: tumble 4.5s ease-in-out infinite; }
@keyframes tumble {
  0%, 100% { transform: rotate(-9deg); }
  50%      { transform: rotate(11deg); }
}

/* ---- The hero pass ---- */
.hero {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
  animation-name: drift;
  animation-timing-function: linear;
  animation-iteration-count: 1;
  animation-fill-mode: both;
}

/* ---- Keep the middle readable under all of that ---- */
.toaster-sky::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(62% 58% at 50% 50%,
    rgba(4,5,12,.62) 0%, rgba(4,5,12,.34) 42%, rgba(4,5,12,0) 82%);
}

/* ---- The card, floated over the scene ---- */
body.toaster-bg .auth-card {
  position: relative;
  z-index: 1;
  background: rgba(10, 12, 26, .72);
  border-color: rgba(150, 162, 225, .30);
  box-shadow: 0 24px 64px rgba(0, 0, 0, .65);
  backdrop-filter: blur(12px) saturate(1.3);
  -webkit-backdrop-filter: blur(12px) saturate(1.3);
}

/* max-content so the bead below is exactly as wide as the title, which parks
   the print head right after the final "r" */
body.toaster-bg .auth-card h1 {
  width: max-content;
  max-width: 100%;
  margin: 0 auto 1.1rem;
}

/* ---- The title, printed in five passes ---- */
/* Pass 1 lays a bead of filament (the raft); passes 2-5 build the letters on top
   of it, bottom band upward, alternating direction the way a real printer does.
   The head ends parked at the top right, just past the final "r". */
.build {
  position: relative;
  display: block;
  line-height: 1;
  padding-bottom: 12px;

  /* Four .18em bands across the glyph height: .80em is near enough the baseline
     and .08em the cap line for this font stack, so every pass lays down ink. */
  --head: 26px;
  --y-bead: calc(1em + 4px - var(--head));
  --y-b0: calc(.62em - var(--head));
  --y-b1: calc(.44em - var(--head));
  --y-b2: calc(.26em - var(--head));
  --y-b3: calc(.08em - var(--head));
}

/* Sizes the box and nothing else - the visible letters are the four layers */
.ghost { color: transparent; }

.layer {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
  background: linear-gradient(180deg, #ffcf95 0%, #f2a25b 55%, #d67f30 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation-duration: .85s;
  animation-timing-function: linear;
  animation-fill-mode: both;
}

/* The plain band is the resting state, so the title still shows if the
   animations never run at all */
.l0 { clip-path: inset(.62em 0 .20em 0); animation-name: lay-rl-0; animation-delay: .97s; }
.l1 { clip-path: inset(.44em 0 .38em 0); animation-name: lay-lr-1; animation-delay: 1.94s; }
.l2 { clip-path: inset(.26em 0 .56em 0); animation-name: lay-rl-2; animation-delay: 2.91s; }
.l3 { clip-path: inset(.08em 0 .74em 0); animation-name: lay-lr-3; animation-delay: 3.88s; }

/* Ink arrives from whichever side the head is travelling from */
@keyframes lay-rl-0 {
  from { clip-path: inset(.62em 0 .20em 100%); }
  to   { clip-path: inset(.62em 0 .20em 0); }
}
@keyframes lay-lr-1 {
  from { clip-path: inset(.44em 100% .38em 0); }
  to   { clip-path: inset(.44em 0 .38em 0); }
}
@keyframes lay-rl-2 {
  from { clip-path: inset(.26em 0 .56em 100%); }
  to   { clip-path: inset(.26em 0 .56em 0); }
}
@keyframes lay-lr-3 {
  from { clip-path: inset(.08em 100% .74em 0); }
  to   { clip-path: inset(.08em 0 .74em 0); }
}

/* Pass 1: the raft */
.bead {
  position: absolute;
  left: 0;
  top: calc(1em + 4px);
  height: 3px;
  width: 100%;
  border-radius: 2px;
  background: linear-gradient(to right, #d8813a, #f0a85a 60%, #ffc179);
  box-shadow: 0 0 7px rgba(240, 160, 80, .4);
  animation: lay-bead .85s linear both;
}

@keyframes lay-bead { from { width: 0; } to { width: 100%; } }

.carriage {
  position: absolute;
  left: 100%;
  top: var(--y-b3);
  transform: translateX(-50%);
  animation: carriage 4.73s linear both;
}

.printhead {
  display: block;
  width: 24px;
  height: var(--head);
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .55));
}

/* Sweep, step up, sweep back - five passes, ending on the right */
@keyframes carriage {
  0%    { left: 0;    top: var(--y-bead); }
  18%   { left: 100%; top: var(--y-bead); }
  20.5% { left: 100%; top: var(--y-b0); }
  38.5% { left: 0;    top: var(--y-b0); }
  41%   { left: 0;    top: var(--y-b1); }
  59%   { left: 100%; top: var(--y-b1); }
  61.5% { left: 100%; top: var(--y-b2); }
  79.5% { left: 0;    top: var(--y-b2); }
  82%   { left: 0;    top: var(--y-b3); }
  100%  { left: 100%; top: var(--y-b3); }
}

/* Molten glow under the nozzle */
.carriage::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -3px;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 198, 124, .95) 0%, rgba(255, 150, 60, 0) 70%);
  animation: tip-heat 1.1s ease-in-out infinite;
}

@keyframes tip-heat {
  0%, 100% { opacity: .5; }
  50%      { opacity: 1; }
}

body.toaster-bg input { background: rgba(6, 8, 18, .7); }

/* The scene stays, nothing moves */
@media (prefers-reduced-motion: reduce) {
  .stars, .sprite, .sprite img, .celestial, .hero,
  .layer, .bead, .carriage, .carriage::after { animation: none !important; }
}
