/* Night over Hoth.
 *
 * Everything behind the table: sky, stars, the fleet holding station above the
 * ridge, walkers coming over it, and the snow coming down between us and them.
 * All of it is one still image with a few slow transforms laid on top - nothing
 * here reacts to the game, it is only the weather the battle happens in.
 */

#viewport {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: #030711;
}

#sky, #starfield, #fleet, #ridge, #walkers, #drift, #grade {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* -------------------------------------------------------------------- sky */

/* The painted sky, dropped to night and pushed cold. Below the horizon line
   the snow field takes over: bright enough to read as snow, dark enough that
   the board sits on it rather than in front of it. */
/* Cold and blue all the way up. The painted sky is dropped to night and left
   at its own hue - pushing it any warmer turns the whole window green, and a
   green sky is the one thing this planet has never had. */
#sky {
  image-rendering: pixelated;
  background-color: #050c1c;
  background-image:
    url("../images/sky-default-000.png"),
    linear-gradient(to bottom,
      #04081a 0%, #060e26 26%, #0a1a3a 44%,
      #113054 50%, #183c62 52%, #0d2040 62%, #060f22 100%);
  background-repeat: repeat-x, no-repeat;
  background-position: center top, center;
  background-size: auto 48%, cover;
  filter: brightness(0.4) saturate(0.85);
}

/* A cold aurora hanging over the ridge - the one soft thing on the screen. */
#sky::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 40% at 22% 30%, rgba(64, 150, 220, 0.13), transparent 62%),
    radial-gradient(90% 34% at 78% 22%, rgba(110, 96, 220, 0.11), transparent 64%);
  filter: blur(2px);
}

/* ------------------------------------------------------------------ stars */

/* Two fields tiled at different sizes, so they never line up into a lattice.
   Faded out towards the ridge, where the sky is brightest. */
#starfield {
  bottom: 50%;
  background-image:
    radial-gradient(1.3px 1.3px at 24px 31px, #dbeaff 50%, transparent 51%),
    radial-gradient(1px 1px at 97px 14px, #a8c6ea 50%, transparent 51%),
    radial-gradient(1.7px 1.7px at 148px 74px, #ffffff 50%, transparent 51%),
    radial-gradient(1px 1px at 63px 108px, #b9d4f5 50%, transparent 51%),
    radial-gradient(1.2px 1.2px at 181px 47px, #cfe3ff 50%, transparent 51%),
    radial-gradient(1px 1px at 116px 133px, #a8c6ea 50%, transparent 51%);
  background-size: 211px 157px;
  mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
  opacity: 0.9;
}
#starfield::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(1.1px 1.1px at 41px 22px, #e6f1ff 50%, transparent 51%),
    radial-gradient(1.9px 1.9px at 122px 63px, #ffffff 50%, transparent 51%),
    radial-gradient(1.4px 1.4px at 70px 111px, #ffe9c4 50%, transparent 51%),
    radial-gradient(1px 1px at 154px 96px, #b9d4f5 50%, transparent 51%);
  background-size: 167px 139px;
  mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
  animation: twinkle 5.5s ease-in-out infinite;
}
@keyframes twinkle { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }

/* ------------------------------------------------------------- the fleet */

/* Two wedges holding station. They do not move so much as hang, which is the
   whole point of them: the sky is occupied before the first die is thrown. */
.destroyer {
  position: absolute;
  display: block;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 60'%3E%3Cpath d='M3 40 L150 12 L196 19 L196 45 L58 46 Z' fill='%23172943'/%3E%3Cpath d='M3 40 L150 12 L196 19 L186 21 L147 16 Z' fill='%2335507a'/%3E%3Crect x='148' y='2' width='38' height='11' fill='%231d3050'/%3E%3Crect x='150' y='2' width='34' height='2' fill='%2335507a'/%3E%3Ccircle cx='156' cy='1.5' r='3.2' fill='%231d3050'/%3E%3Ccircle cx='176' cy='1.5' r='3.2' fill='%231d3050'/%3E%3Cg fill='%2386dcff'%3E%3Crect x='191' y='23' width='6' height='5'/%3E%3Crect x='191' y='33' width='6' height='5'/%3E%3C/g%3E%3Cg fill='%23dcecff' opacity='.65'%3E%3Crect x='122' y='27' width='2' height='2'/%3E%3Crect x='96' y='31' width='2' height='2'/%3E%3Crect x='64' y='36' width='2' height='2'/%3E%3Crect x='170' y='6' width='2' height='2'/%3E%3C/g%3E%3C/svg%3E");
  filter: drop-shadow(0 6px 18px rgba(2, 6, 14, 0.9));
}
.destroyer.d1 {
  left: 5%;
  top: 12%;
  width: 380px;
  height: 114px;
  opacity: 0.95;
  animation: hold-station 34s ease-in-out infinite;
}
.destroyer.d2 {
  right: 8%;
  top: 23%;
  width: 210px;
  height: 63px;
  opacity: 0.6;
  transform: scaleX(-1);
  animation: hold-station 46s ease-in-out infinite reverse;
}
@keyframes hold-station {
  0%, 100% { translate: 0 0; }
  50% { translate: -14px 7px; }
}

/* ------------------------------------------------------------ the horizon */

#ridge {
  image-rendering: pixelated;
  background-image: url("../images/horizon-default-000.png");
  background-repeat: repeat-x;
  background-position: center 46%;
  background-size: auto 128px;
  filter: brightness(0.46) saturate(0.9) contrast(1.05);
}

/* The snow field the ridge stands on: lit along the crest and dropping into
   the dark long before it reaches the table. */
#ridge::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 52%;
  bottom: 0;
  background:
    linear-gradient(to bottom,
      rgba(150, 196, 238, 0.38) 0%, rgba(52, 92, 140, 0.42) 8%,
      rgba(14, 32, 60, 0.72) 26%, rgba(4, 10, 22, 0.95) 62%, rgba(2, 6, 14, 1) 100%);
}

/* --------------------------------------------------------------- walkers */

/* Coming over the ridge, four legs at a time. Held to a crawl: at this size a
   walker that visibly strides reads as a toy, and one that barely moves reads
   as something very large a long way off. */
.walker {
  position: absolute;
  display: block;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 132 112'%3E%3Cg fill='%23081426'%3E%3Cpath d='M4 30 h30 v16 h-6 l-3 7 h-5 l-3-7 h-13 z'/%3E%3Cpath d='M30 27 l23 -9 l7 15 l-25 10 z'/%3E%3Cpath d='M47 15 h67 l8 11 v19 l-8 11 h-67 l-7 -11 v-19 z'/%3E%3C/g%3E%3Cg stroke='%23081426' stroke-width='7' fill='none' stroke-linecap='square'%3E%3Cpath d='M62 52 l-7 24 l11 30'/%3E%3Cpath d='M76 52 l-4 24 l9 30'/%3E%3Cpath d='M99 52 l7 24 l-9 30'/%3E%3Cpath d='M112 52 l4 24 l-7 30'/%3E%3C/g%3E%3C/svg%3E");
}
.walker.w1 {
  left: 4%;
  top: 41%;
  width: 132px;
  height: 112px;
  opacity: 0.9;
  animation: march 210s linear infinite, plod 4.4s ease-in-out infinite;
}
.walker.w2 {
  left: 22%;
  top: 43.4%;
  width: 92px;
  height: 78px;
  opacity: 0.72;
  animation: march 260s linear infinite, plod 5.1s ease-in-out infinite;
  animation-delay: 0s, -1.7s;
}
.walker.w3 {
  right: 12%;
  top: 44.6%;
  width: 68px;
  height: 58px;
  opacity: 0.55;
  transform: scaleX(-1);
  animation: march-back 300s linear infinite, plod 5.8s ease-in-out infinite;
  animation-delay: 0s, -3.2s;
}
@keyframes march { from { translate: 0 0; } to { translate: 300px 0; } }
@keyframes march-back { from { translate: 0 0; } to { translate: -240px 0; } }
@keyframes plod {
  0%, 100% { rotate: 0deg; }
  50% { rotate: 0.7deg; }
}

/* ------------------------------------------------------------------ snow */

/* Two sheets of it, one near and quick, one far and slow, each twice the
   height of the window and slid down through a full tile. */
#drift::before,
#drift::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -100%;
  height: 200%;
  background-repeat: repeat;
}
#drift::before {
  background-image:
    radial-gradient(1.6px 1.6px at 13% 6%, rgba(255, 255, 255, 0.75) 50%, transparent 51%),
    radial-gradient(1.4px 1.4px at 46% 14%, rgba(255, 255, 255, 0.6) 50%, transparent 51%),
    radial-gradient(1.8px 1.8px at 77% 9%, rgba(255, 255, 255, 0.8) 50%, transparent 51%),
    radial-gradient(1.4px 1.4px at 29% 22%, rgba(255, 255, 255, 0.55) 50%, transparent 51%),
    radial-gradient(1.6px 1.6px at 62% 27%, rgba(255, 255, 255, 0.7) 50%, transparent 51%),
    radial-gradient(1.4px 1.4px at 92% 19%, rgba(255, 255, 255, 0.6) 50%, transparent 51%);
  background-size: 420px 300px;
  animation: fall 17s linear infinite;
}
#drift::after {
  background-image:
    radial-gradient(1px 1px at 22% 11%, rgba(214, 234, 255, 0.55) 50%, transparent 51%),
    radial-gradient(1px 1px at 58% 18%, rgba(214, 234, 255, 0.45) 50%, transparent 51%),
    radial-gradient(1.2px 1.2px at 84% 25%, rgba(214, 234, 255, 0.5) 50%, transparent 51%),
    radial-gradient(1px 1px at 38% 31%, rgba(214, 234, 255, 0.4) 50%, transparent 51%);
  background-size: 300px 220px;
  animation: fall 31s linear infinite;
  opacity: 0.75;
}
@keyframes fall {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(-26px, 300px, 0); }
}

/* ---------------------------------------------------------------- grading */

/* The last pass over the whole scene: pull the corners down so the table is
   the brightest thing on the screen, and lay a faint scan over everything so
   the whole picture reads as something being watched rather than something
   being lit. */
#grade {
  background:
    radial-gradient(ellipse 78% 62% at 50% 46%, rgba(6, 14, 28, 0) 0%, rgba(4, 9, 20, 0.62) 78%, rgba(2, 5, 12, 0.9) 100%),
    repeating-linear-gradient(to bottom, rgba(120, 180, 240, 0.035) 0 1px, transparent 1px 3px);
  z-index: 2;
}

@media (prefers-reduced-motion: reduce) {
  #starfield::after, .destroyer, .walker, #drift::before, #drift::after {
    animation: none;
  }
}
