/* Roaming Rover. The company site (inorganic.cc) keeps to the two ends of the
   waldgeist palette; this page is where the whole of it is spent. Every colour
   below is a palette member, and every picture is the game's own sprite sheet. */

@font-face {
  font-family: "Press Start 2P";
  src: url("fonts/press-start-2p.ttf") format("truetype");
  font-display: swap;
}

:root {
  --ink: #0b1016;
  --deep: #141f25;
  --cliff: #212528;
  --slate: #323b42;
  --cream: #e3ddd1;
  --bone: #bdbbae;
  --mist: #879ea3;
  --sand: #a6884a;
  --ochre: #906c30;
  --clay: #825337;
  --rust: #83473d;
  --wine: #612638;
  --silt: #696353;
  --dark-silt: #4f493b;
  --moss: #5f7b53;
  --teal: #3b6d62;
  --water: #245273;
  --sky: #4e7499;
  --steel: #5e7e8b;

  --pixel: "Press Start 2P", ui-monospace, Menlo, monospace;
  --gutter: clamp(16px, 5vw, 80px);
  --tile: 64px; /* one 16px tile at x4, the game's own cell */
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--cream);
  font: 11px/2.2 var(--pixel);
}

p, h1, h2, h3 { margin: 0; font-weight: 400; }
img { image-rendering: pixelated; }
a { color: inherit; text-underline-offset: 0.5em; text-decoration-thickness: 2px; }
a:hover { opacity: 0.8; }
a:focus-visible { outline: 3px solid var(--cream); outline-offset: 4px; }

.wrap { max-width: 1280px; margin: 0 auto; padding-inline: var(--gutter); }

/* Ground: one generated map (scripts/build_background.py), the game's real
   autotiled terrain, cut into a slice per section. Read top to bottom it walks
   down the tiers: mesa, plain, then the basin at night. All three slices are the
   same width and centred, so cliffs and shores line up across the joins. */

.map { background-repeat: no-repeat; background-size: calc(37 * var(--tile)) auto; image-rendering: pixelated; }
/* Anchored to the bottom, so the mesa's cliff edge always sits just above
   where the opening screen ends, however tall the screen is. */
.map--mesa { background-color: #a48648; background-image: url("img/map-mesa.png"); background-position: center bottom; }
.map--plain { background-color: var(--silt); background-image: url("img/map-plain.png"); background-position: center top; }
.map--basin { background-color: #33343a; background-image: url("img/map-basin.png"); background-position: center top; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Panels: the game's UI is dark boxes with notched pixel corners. */

.panel {
  background: var(--ink);
  margin: 4px;
  box-shadow: 0 -4px 0 0 var(--ink), 0 4px 0 0 var(--ink), -4px 0 0 0 var(--ink), 4px 0 0 0 var(--ink);
}

/* Sprites: a strip of frames behind a one-frame window, stepped at 10 fps,
   the rate every animation in the game is authored at. --s is the scale. */

.sprite {
  display: block;
  overflow: hidden;
  width: calc(var(--fw) * var(--s) * 1px);
  height: calc(var(--fh) * var(--s) * 1px);
  flex: none;
}
.sprite img {
  display: block;
  height: 100%;
  width: auto;
  animation: frames calc(var(--n) * 100ms) steps(var(--n)) infinite;
}
@keyframes frames { to { transform: translateX(-100%); } }

/* Hero: the mesa floor, the title, and nothing else but the rover passing. */

.hero {
  min-height: 100vh;
  min-height: 100svh;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.hero-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: clamp(32px, 5vw, 56px);
  padding-block: 64px 160px;
}

/* The title is the game's own logo (138 x 36), scaled in whole steps so every
   source pixel stays square: x2 on a phone up to x6 on a large screen. */
.title { margin: 0; line-height: 0; }
.logo { display: block; width: 276px; height: auto; image-rendering: pixelated; }
@media (min-width: 480px) { .logo { width: 414px; } }
@media (min-width: 700px) { .logo { width: 552px; } }
@media (min-width: 960px) { .logo { width: 690px; } }
@media (min-width: 1280px) { .logo { width: 828px; } }

.hero-card { max-width: 640px; padding: 28px clamp(20px, 4vw, 40px); display: flex; flex-direction: column; gap: 16px; align-items: center; }
.tagline { font-size: clamp(14px, 2.2vw, 22px); line-height: 1.7; }
.status { font-size: 9px; color: var(--sand); }

.drive {
  position: absolute;
  bottom: 56px;
  left: 0;
  animation: drive 16s linear infinite;
}
@keyframes drive { from { transform: translateX(-160px); } to { transform: translateX(100vw); } }

.scroll {
  position: absolute;
  bottom: 12px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  font-size: 9px;
  text-decoration: none;
  color: var(--bone);
}

.label { font-size: 9px; letter-spacing: 0.08em; color: var(--mist); }

/* Mine, build, connect, capture: told by the map itself. The section is exactly the
   plain slice's sixteen rows, so its cells line up with the tiles under them,
   and the join to the basin falls on the row the map has it on. The story runs
   down the centre column, which is the part of the map a phone sees. */

.stage { position: relative; height: calc(16 * var(--tile)); overflow: hidden; }

/* One map cell: --cx columns from the centre line, --cy rows from the top.
   --oy is the sprite's offset in its game scene, in world pixels. */
.on-cell {
  position: absolute;
  left: calc(50% + var(--cx) * var(--tile));
  top: calc((var(--cy) + 0.5) * var(--tile) + var(--oy, 0px));
  transform: translate(-50%, -50%);
}

/* A name tag to the left of its row; --gap clears the sprite's own width. */
.tag {
  position: absolute;
  right: calc(50% + var(--gap));
  top: calc((var(--cy) + 0.5) * var(--tile));
  transform: translateY(-50%);
  margin: 0;
  padding: 8px 12px;
  font-size: clamp(9px, 1.2vw, 12px);
  line-height: 1.6;
  color: var(--cream);
}

/* The signal: pixels running down the centre line from the reactor, down the
   basin ramp and into the night. Two pieces, one per section, on the same 16px
   rhythm, so they read as one line across the join. */
.signal {
  display: block;
  width: 4px;
  margin-left: -2px;
  background: repeating-linear-gradient(to bottom, var(--sand) 0 8px, transparent 8px 16px);
  animation: signal 0.4s steps(4) infinite;
}
@keyframes signal { to { background-position: 0 16px; } }
.signal--stage { position: absolute; left: 50%; top: calc(12 * var(--tile)); bottom: 0; }
.connected .signal { position: relative; left: 50%; height: clamp(64px, 10vw, 128px); }

/* Connected: where the signal lands. Centred, and never wider than a phone
   needs to read it comfortably. */
.connected { padding-bottom: clamp(64px, 9vw, 128px); }
.live {
  max-width: 640px;
  margin: 4px auto;
  padding: clamp(24px, 4vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 24px;
  text-align: center;
  align-items: center;
}
.live h2 { font-size: clamp(16px, 2.8vw, 26px); line-height: 1.5; }
.live-tag { display: inline-flex; align-items: center; gap: 10px; font-size: 9px; letter-spacing: 0.08em; color: var(--sand); }
.led { width: 8px; height: 8px; background: var(--sand); animation: led 1.2s steps(1, end) infinite; }
@keyframes led { 0%, 40% { opacity: 1; } 50%, 100% { opacity: 0.25; } }

/* The sensor trace: a stepped wave sliding left by exactly one period. */
.trace { width: 100%; max-width: 360px; height: 48px; color: var(--mist); shape-rendering: crispEdges; }
.trace-strip { animation: trace 3.2s steps(32) infinite; }
@keyframes trace { to { transform: translateX(-64px); } }

.connected-text { max-width: 44ch; font-size: clamp(10px, 1.3vw, 12px); color: var(--bone); }
.note { width: 100%; padding: 16px 20px; border: 4px solid var(--slate); display: flex; flex-direction: column; gap: 8px; }
.note .label { color: var(--sand); }

/* Footer */

.footer { background: var(--ink); border-top: 4px solid var(--cliff); }
.footer .wrap { padding-block: 28px 36px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 32px; font-size: 9px; color: var(--mist); }
.footer a { display: inline-flex; align-items: center; min-height: 44px; }

/* The crossing is a fixed time over a width that varies, so the same duration
   would crawl on a narrow screen. These keep the rover near 100px/s throughout. */
@media (max-width: 1024px) {
  .drive { animation-duration: 10s; }
}

@media (max-width: 640px) {
  .drive { bottom: 64px; animation-duration: 6s; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .sprite img, .drive, .signal, .led, .trace-strip { animation: none !important; }
}
