:root {
  --bg: #080a0e;
  --bg-2: #10141b;
  --panel: rgba(21, 26, 34, 0.93);
  --panel-edge: rgba(233, 164, 75, 0.16);
  --ink: #e4e1da;
  --ink-dim: #a09a8f;
  --ink-faint: #6d6a63;
  --accent: #e9a44b;
  --accent-2: #7fb6e8;
  --gold: #ffd166;
  --danger: #ff8a7a;
  --radius: 14px;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  --font: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
  /* Icons must name an emoji font explicitly. Left to fall back through the
     serif stack, macOS sizes them against the serif font's em box (and picks
     monochrome glyphs for some characters), so they drift out of proportion
     with the rest of the page as you zoom. Never put this first in a stack
     used for text — Apple Color Emoji also maps the digits, for keycaps. */
  --emoji: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Twemoji Mozilla", sans-serif;
}

/* Every emoji in the UI goes through this: a fixed square box, emoji font,
   and a size in `em` so it scales with page zoom exactly like the text does. */
.emoji,
.brand-mark,
.loader-icon,
.gen-icon,
.upg-icon,
.ach-emoji,
.parcel {
  font-family: var(--emoji);
  font-variant-emoji: emoji;
  font-style: normal;
  line-height: 1;
}

* {
  box-sizing: border-box;
}

/* Class-level `display` would otherwise beat the browser's [hidden] rule. */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  min-height: 100%;
}

body {
  background: radial-gradient(120% 90% at 50% -10%, #1b2029 0%, var(--bg-2) 45%, var(--bg) 100%);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  padding-bottom: 4.5rem;
}

#bg {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  opacity: 0.8;
  pointer-events: none;
}

#parcel-layer {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* ---------- top bar ---------- */

/* The counter stays put while the rest of the page scrolls under it. The
   ::before stretches the backing to the full viewport width, since the bar
   itself is centred and capped. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  padding: 1.1rem clamp(0.9rem, 3vw, 2.2rem) 0.9rem;
  max-width: 1560px;
  margin: 0 auto;
}

.topbar::before {
  content: "";
  position: absolute;
  inset: 0 calc(-50vw + 50%);
  background: linear-gradient(
    to bottom,
    rgba(8, 10, 14, 0.97) 0%,
    rgba(8, 10, 14, 0.93) 68%,
    rgba(8, 10, 14, 0) 100%
  );
  /* No backdrop-filter here. The bar is already 97% opaque, so a blur behind
     it bought almost nothing visually — but because the map animates behind
     it, the compositor had to recompute a full-width blur every single frame.
     That was the most expensive thing on the page by a wide margin. */
  pointer-events: none;
  z-index: -1;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
.brand-mark {
  font-size: 2rem;
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
  filter: drop-shadow(0 0 12px rgba(233, 164, 75, 0.4));
}
.brand h1 {
  font-size: 1.5rem;
  letter-spacing: 0.04em;
}
.tagline {
  margin: 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
  font-style: italic;
}

.counter {
  margin-left: auto;
  text-align: right;
}
.counter-main {
  font-family: var(--mono);
  font-size: clamp(1.5rem, 5vw, 2.3rem);
  font-weight: 600;
  color: #fff;
  text-shadow: 0 0 26px rgba(233, 164, 75, 0.3);
  line-height: 1.1;
}
.counter-main .unit {
  font-family: var(--font);
  font-size: 0.5em;
  color: var(--ink-dim);
  font-weight: 400;
}
.counter-sub {
  font-size: 0.85rem;
  color: var(--accent);
  font-family: var(--mono);
}
#buff-hint {
  color: var(--gold);
}

.buffbar {
  display: flex;
  gap: 0.4rem;
  justify-content: flex-end;
  margin-top: 0.35rem;
}
.buff-chip {
  font-size: 0.75rem;
  font-family: var(--mono);
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: rgba(255, 209, 102, 0.16);
  border: 1px solid rgba(255, 209, 102, 0.45);
  color: var(--gold);
  animation: pulse-soft 1.6s ease-in-out infinite;
}

.spike-badge {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  padding: 0.4rem 0.8rem;
  border-radius: var(--radius);
  background: rgba(127, 182, 232, 0.08);
  border: 1px solid rgba(127, 182, 232, 0.25);
}
.spike-count {
  font-family: var(--mono);
  font-size: 1.05rem;
  color: var(--accent-2);
}
.spike-label {
  font-size: 0.72rem;
  color: var(--ink-faint);
}

/* ---------- layout ---------- */

.layout {
  position: relative;
  z-index: 2;
  max-width: 1560px;
  margin: 0 auto;
  padding: 0.8rem clamp(0.9rem, 3vw, 2.2rem);
  display: grid;
  grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
  gap: 1.1rem;
  align-items: start;
}

/* Likewise no backdrop-filter: the panels sit over an animating canvas, so a
   blurred backdrop is re-rendered every frame for something you can barely
   see. Slightly more opaque instead, which reads much the same. */
.panel {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.1rem;
}

.yard-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  position: sticky;
  top: 0.8rem;
}

/* ---------- the loader button ---------- */

.loader {
  position: relative;
  width: 190px;
  height: 190px;
  border-radius: 50%;
  border: 1px solid rgba(233, 164, 75, 0.3);
  background: radial-gradient(circle at 50% 35%, #3a2f22 0%, #1f1a14 60%, #12100c 100%);
  color: var(--ink);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition:
    transform 0.08s ease,
    box-shadow 0.25s ease;
  box-shadow:
    0 0 40px rgba(233, 164, 75, 0.12),
    inset 0 0 30px rgba(0, 0, 0, 0.65);
  user-select: none;
  touch-action: manipulation;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
.loader:hover {
  box-shadow:
    0 0 60px rgba(233, 164, 75, 0.24),
    inset 0 0 30px rgba(0, 0, 0, 0.55);
}
.loader:active,
.loader.pressed {
  transform: scale(0.955);
}
.loader-icon {
  font-size: 4.4rem;
  width: 5rem;
  height: 5rem;
  display: grid;
  place-items: center;
  grid-area: 1 / 1;
  transform: translateY(-8px);
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55));
}
.loader-label {
  grid-area: 1 / 1;
  align-self: end;
  margin-bottom: 26px;
  font-size: 0.75rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.loader-glow {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1px solid rgba(233, 164, 75, 0.18);
  animation: breathe 4.5s ease-in-out infinite;
  pointer-events: none;
}

/* While held, a ring sweeps round the button and completes on each automatic
   haul, so the rhythm of the hold is visible. Keep this duration in step with
   HOLD_INTERVAL in ui.js. */
.loader-ring {
  position: absolute;
  inset: -5px;
  width: calc(100% + 10px);
  height: calc(100% + 10px);
  transform: rotate(-90deg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.loader-ring circle {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 295.3; /* 2 * pi * r, with r = 47 */
  stroke-dashoffset: 295.3;
}
.loader.holding .loader-ring {
  opacity: 0.9;
}
.loader.holding .loader-ring circle {
  animation: hold-charge 0.75s linear infinite;
}

.haul-value {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-dim);
}
.haul-value strong {
  font-family: var(--mono);
  color: var(--accent);
}
.haul-compare {
  display: block;
  font-size: 0.72rem;
  color: var(--ink-faint);
}

.float-num {
  position: fixed;
  z-index: 70;
  pointer-events: none;
  font-family: var(--mono);
  font-size: 1rem;
  color: var(--accent);
  text-shadow: 0 0 10px rgba(0, 0, 0, 0.85);
  animation: floatup 0.95s ease-out forwards;
}

.quickstats {
  display: flex;
  gap: 0.4rem;
  width: 100%;
  font-family: var(--mono);
  font-size: 0.8rem;
}
.quickstats div {
  flex: 1;
  background: rgba(255, 255, 255, 0.035);
  border-radius: 10px;
  padding: 0.45rem 0.3rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.qs-label {
  font-family: var(--font);
  font-size: 0.7rem;
  color: var(--ink-faint);
}

/* ---------- regauge ---------- */

.regauge-box {
  width: 100%;
  border-top: 1px dashed rgba(127, 182, 232, 0.22);
  padding-top: 0.8rem;
  text-align: center;
}
.regauge-box h3 {
  color: var(--accent-2);
  font-size: 1.05rem;
}
.regauge-copy {
  font-size: 0.78rem;
  color: var(--ink-faint);
  margin: 0.3rem 0 0.5rem;
}
.regauge-gain {
  font-size: 0.85rem;
  margin: 0 0 0.5rem;
  font-family: var(--mono);
}
.regauge-gain strong {
  color: var(--accent-2);
}
.regauge-next {
  font-size: 0.72rem;
  color: var(--ink-faint);
  margin: 0.45rem 0 0;
}

/* ---------- buttons ---------- */

.btn {
  font-family: var(--font);
  font-size: 0.85rem;
  padding: 0.45rem 1rem;
  border-radius: 9px;
  border: 1px solid rgba(233, 164, 75, 0.35);
  background: rgba(233, 164, 75, 0.12);
  color: var(--ink);
  cursor: pointer;
  transition:
    background 0.15s ease,
    border-color 0.15s ease,
    opacity 0.15s ease;
}
.btn:hover:not(:disabled) {
  background: rgba(233, 164, 75, 0.22);
}
.btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.btn.ghost {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.12);
  color: var(--ink-dim);
}
.btn.ghost:hover {
  background: rgba(255, 255, 255, 0.06);
  color: var(--ink);
}
/* The source link wears the same coat as the footer buttons. */
a.btn {
  display: inline-block;
  text-decoration: none;
  line-height: normal;
}
.btn.danger {
  border-color: rgba(127, 182, 232, 0.5);
  background: rgba(127, 182, 232, 0.14);
  color: var(--accent-2);
}
.btn.danger:hover:not(:disabled) {
  background: rgba(127, 182, 232, 0.24);
}
.danger-text {
  color: var(--danger) !important;
}

/* ---------- the three shops, side by side ---------- */

.shops {
  display: grid;
  /* auto-fit collapses to two columns, then one, as the space runs out. */
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 1.2rem;
  align-items: start;
}

.shop {
  min-width: 0;
}

.shop-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  flex-wrap: wrap;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  padding-bottom: 0.45rem;
  margin-bottom: 0.7rem;
}
.shop-head h2 {
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.03em;
}

/* Each shop scrolls in its own right, so all three stay on screen together. */
.shop-list {
  max-height: min(64vh, 660px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 0.3rem;
}
.shop-list::-webkit-scrollbar {
  width: 8px;
}
.shop-list::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.12);
  border-radius: 4px;
}
.shop-list::-webkit-scrollbar-track {
  background: transparent;
}
.shop-list {
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}

.logbook {
  margin-top: 1.2rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding-top: 0.7rem;
}
.logbook > summary {
  cursor: pointer;
  font-size: 0.95rem;
  color: var(--ink-dim);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.logbook > summary::-webkit-details-marker {
  display: none;
}
.logbook > summary::before {
  content: "▸";
  color: var(--accent);
  transition: transform 0.15s ease;
}
.logbook[open] > summary::before {
  transform: rotate(90deg);
}
.logbook > summary:hover {
  color: var(--ink);
}
.logbook .statgrid {
  margin-top: 0.8rem;
}

/* ---------- tabs ---------- */

.tabs {
  display: flex;
  gap: 0.3rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  margin-bottom: 0.8rem;
  flex-wrap: wrap;
}
.tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--ink-faint);
  font-family: var(--font);
  font-size: 0.92rem;
  padding: 0.4rem 0.75rem;
  cursor: pointer;
}
.tab:hover {
  color: var(--ink);
}
.tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.pip {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gold);
  vertical-align: middle;
  margin-left: 2px;
  animation: pulse-soft 1.4s infinite;
}

.tabpanel {
  display: none;
}
.tabpanel.active {
  display: block;
}

.buyamt {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.78rem;
  color: var(--ink-faint);
}
.amt {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid transparent;
  color: var(--ink-dim);
  border-radius: 7px;
  padding: 0.2rem 0.6rem;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.78rem;
}
.amt.active {
  border-color: rgba(233, 164, 75, 0.5);
  color: var(--accent);
  background: rgba(233, 164, 75, 0.1);
}

/* Buy-all, and the two automation toggles, in the shop headers. */
.shop-tools {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-wrap: wrap;
}
.chip {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid transparent;
  color: var(--ink-dim);
  border-radius: 7px;
  padding: 0.2rem 0.6rem;
  cursor: pointer;
  font-family: var(--font);
  font-size: 0.76rem;
  white-space: nowrap;
}
.chip:hover:not(:disabled) {
  border-color: rgba(233, 164, 75, 0.45);
  color: var(--accent);
}
.chip:disabled {
  cursor: default;
  opacity: 0.4;
}
.auto-chip {
  border-color: rgba(233, 164, 75, 0.4);
  color: var(--accent);
}
.auto-chip.off {
  border-color: transparent;
  color: var(--ink-faint);
}
.auto-chip.off .emoji {
  filter: grayscale(1);
  opacity: 0.6;
}

/* ---------- rolling stock ---------- */

.gen-list,
.upgrade-list,
.ach-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.gen {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: center;
  padding: 0.6rem 0.75rem;
  border-radius: 11px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  background: rgba(255, 255, 255, 0.025);
  cursor: pointer;
  text-align: left;
  width: 100%;
  color: inherit;
  font: inherit;
  transition:
    border-color 0.15s ease,
    background 0.15s ease,
    transform 0.06s ease;
}
.gen:hover:not(:disabled) {
  border-color: rgba(233, 164, 75, 0.3);
  background: rgba(233, 164, 75, 0.06);
}
.gen:active:not(:disabled) {
  transform: translateY(1px);
}
.gen:disabled {
  cursor: default;
  opacity: 0.55;
}
.gen.locked {
  opacity: 0.42;
  cursor: not-allowed;
}
.gen.locked:hover {
  border-color: rgba(255, 255, 255, 0.06);
  background: rgba(255, 255, 255, 0.025);
}
.gen.affordable {
  border-color: rgba(233, 164, 75, 0.45);
}

.gen-icon {
  font-size: 1.6rem;
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
}
.gen-name {
  font-size: 0.98rem;
  display: block;
}
.gen-blurb {
  font-size: 0.74rem;
  color: var(--ink-faint);
  font-style: italic;
  display: block;
  margin-top: 0.1rem;
}
.gen-out {
  font-size: 0.74rem;
  color: var(--accent);
  font-family: var(--mono);
  display: block;
  margin-top: 0.15rem;
}
.gen-right {
  text-align: right;
  font-family: var(--mono);
}
.gen-cost {
  font-size: 0.86rem;
  color: var(--gold);
  white-space: nowrap;
}
.gen-cost.too-dear {
  color: var(--ink-faint);
}
.gen-owned {
  font-size: 1.15rem;
  color: var(--ink);
}
.gen-tier {
  font-size: 0.68rem;
  color: var(--accent-2);
}

/* ---------- works & spikes ---------- */

.upg {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0.7rem;
  align-items: center;
  padding: 0.55rem 0.7rem;
  border-radius: 11px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.025);
  cursor: pointer;
  text-align: left;
  width: 100%;
  color: inherit;
  font: inherit;
}
.upg:hover:not(:disabled) {
  border-color: rgba(255, 209, 102, 0.35);
  background: rgba(255, 209, 102, 0.05);
}
.upg.affordable {
  border-color: rgba(255, 209, 102, 0.5);
}
.upg:disabled {
  cursor: default;
  opacity: 0.55;
}
.upg-icon {
  font-size: 1.4rem;
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
}
.upg-name {
  font-size: 0.92rem;
}
.upg-desc {
  font-size: 0.75rem;
  color: var(--ink-faint);
}
.upg-effect {
  font-size: 0.75rem;
  color: var(--accent);
}
.upg-cost {
  font-family: var(--mono);
  font-size: 0.85rem;
  color: var(--gold);
  white-space: nowrap;
}
.upg.spike .upg-cost {
  color: var(--accent-2);
}
.upg.bought {
  opacity: 0.5;
}
.upg.bought .upg-cost {
  color: var(--ink-faint);
}

/* A driven spike is permanent and worth being able to pick out at a glance, so
   it reads as a filled-in plaque rather than as another greyed-out row. */
.upg-driven {
  display: none;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-2);
  border: 1px solid rgba(127, 182, 232, 0.45);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  white-space: nowrap;
}
.upg-driven::before {
  content: "✓ ";
}
.upg.spike.bought {
  opacity: 1;
  border-color: rgba(127, 182, 232, 0.45);
  background: linear-gradient(90deg, rgba(127, 182, 232, 0.14), rgba(127, 182, 232, 0.03));
  box-shadow: inset 3px 0 0 var(--accent-2);
}
.upg.spike.bought .upg-name {
  color: var(--accent-2);
}
.upg.spike.bought .upg-desc {
  opacity: 0.75;
}
.upg.spike.bought .upg-cost {
  display: none;
}
.upg.spike.bought .upg-driven {
  display: inline-block;
}

.empty {
  color: var(--ink-faint);
  font-style: italic;
  font-size: 0.85rem;
  text-align: center;
  padding: 1.2rem 0;
}
.spike-intro {
  font-size: 0.8rem;
  color: var(--ink-faint);
  margin: 0 0 0.7rem;
}

.owned-strip {
  margin-top: 1.1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  padding-top: 0.6rem;
}
.owned-strip h4 {
  font-size: 0.78rem;
  color: var(--ink-faint);
  font-weight: 400;
}
.owned-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-top: 0.4rem;
}
.owned-list span {
  font-size: 1rem;
  opacity: 0.75;
  cursor: help;
}

/* ---------- logbook ---------- */

.statgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.5rem;
  margin: 0;
}
.statgrid div {
  background: rgba(255, 255, 255, 0.03);
  border-radius: 10px;
  padding: 0.5rem 0.65rem;
}
.statgrid dt {
  font-size: 0.72rem;
  color: var(--ink-faint);
}
.statgrid dd {
  margin: 0.1rem 0 0;
  font-family: var(--mono);
  font-size: 0.95rem;
}

.ach-head {
  margin: 1.2rem 0 0.6rem;
  font-size: 0.95rem;
}
.ach-head small {
  color: var(--ink-faint);
  font-weight: 400;
  font-size: 0.72rem;
}
.ach-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 0.4rem;
}
.ach {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  padding: 0.45rem 0.55rem;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.05);
}
.ach.got {
  border-color: rgba(233, 164, 75, 0.35);
  background: rgba(233, 164, 75, 0.07);
}
.ach-emoji {
  font-size: 1.2rem;
  width: 1.5rem;
  height: 1.5rem;
  display: grid;
  place-items: center;
  flex: none;
  filter: grayscale(1);
  opacity: 0.4;
}
.ach.got .ach-emoji {
  filter: none;
  opacity: 1;
}
.ach-name {
  font-size: 0.82rem;
}
.ach-desc {
  font-size: 0.7rem;
  color: var(--ink-faint);
}

/* ---------- express parcel ---------- */

.parcel {
  position: absolute;
  width: 62px;
  height: 62px;
  border: none;
  background: none;
  font-size: 2.4rem;
  cursor: pointer;
  pointer-events: auto;
  filter: drop-shadow(0 0 16px rgba(255, 209, 102, 0.85));
  animation:
    parcel-in 0.4s ease-out,
    jostle 2.4s ease-in-out 0.4s infinite;
  z-index: 61;
}
.parcel:hover {
  transform: scale(1.12);
}
.parcel.gone {
  animation: pop 0.35s ease-out forwards;
  pointer-events: none;
}

/* ---------- footer / toast / modal ---------- */

.footer {
  position: relative;
  z-index: 2;
  max-width: 1560px;
  margin: 0.6rem auto 0;
  padding: 0.4rem clamp(0.9rem, 3vw, 2.2rem) 1.4rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}
.footer-note {
  font-size: 0.72rem;
  color: var(--ink-faint);
  margin-left: auto;
}

.toast-layer {
  position: fixed;
  left: 50%;
  bottom: 1.4rem;
  transform: translateX(-50%);
  z-index: 80;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: center;
  pointer-events: none;
  width: min(92vw, 460px);
}
.toast {
  background: rgba(16, 20, 27, 0.96);
  border: 1px solid rgba(233, 164, 75, 0.35);
  border-radius: 11px;
  padding: 0.55rem 0.95rem;
  font-size: 0.85rem;
  box-shadow: var(--shadow);
  animation:
    toast-in 0.3s ease-out,
    toast-out 0.4s ease-in forwards;
  animation-delay: 0s, 3.6s;
  text-align: center;
}
.toast.gold {
  border-color: rgba(255, 209, 102, 0.55);
  color: var(--gold);
}

.modal {
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  background: #10141b;
  color: var(--ink);
  padding: 1.2rem;
  max-width: min(94vw, 520px);
  box-shadow: var(--shadow);
}
.modal::backdrop {
  background: rgba(0, 0, 0, 0.62);
}
.modal p {
  font-size: 0.85rem;
  color: var(--ink-dim);
}
.modal textarea {
  width: 100%;
  font-family: var(--mono);
  font-size: 0.75rem;
  background: #070a0d;
  color: var(--accent);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 9px;
  padding: 0.5rem;
  resize: vertical;
}
.modal menu {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  padding: 0;
  margin: 0.8rem 0 0;
}

/* ---------- the vista ---------- */

/* Open ground below the game so the rail survey on the fixed background canvas
   can be watched with nothing on top of it. */
.vista {
  position: relative;
  z-index: 1;
  min-height: 88vh;
  display: grid;
  place-items: center;
  pointer-events: none;
}
.vista-note {
  margin: 0;
  align-self: start;
  padding-top: 1.5rem;
  font-size: 0.7rem;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--ink-faint);
  opacity: 0.5;
}

/* ---------- animations ---------- */

@keyframes floatup {
  from {
    opacity: 1;
    transform: translate(-50%, 0) scale(1);
  }
  to {
    opacity: 0;
    transform: translate(-50%, -70px) scale(1.15);
  }
}
@keyframes breathe {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.5;
  }
  50% {
    transform: scale(1.045);
    opacity: 0.15;
  }
}
@keyframes pulse-soft {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}
@keyframes hold-charge {
  from {
    stroke-dashoffset: 295.3;
  }
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes jostle {
  0%,
  100% {
    transform: translateY(0) rotate(-5deg);
  }
  50% {
    transform: translateY(-12px) rotate(5deg);
  }
}
@keyframes parcel-in {
  from {
    opacity: 0;
    transform: scale(0.3);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes pop {
  to {
    opacity: 0;
    transform: scale(2.1) rotate(20deg);
  }
}
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes toast-out {
  to {
    opacity: 0;
    transform: translateY(-10px);
  }
}

/* ---------- responsive ---------- */

@media (max-width: 860px) {
  .layout {
    grid-template-columns: 1fr;
  }
  .yard-panel {
    position: static;
  }
  .loader {
    width: 160px;
    height: 160px;
  }
  .loader-icon {
    font-size: 3.6rem;
  }
}

@media (max-width: 520px) {
  .topbar {
    padding-top: 0.8rem;
  }
  .brand h1 {
    font-size: 1.2rem;
  }
  .tagline {
    display: none;
  }
  .gen-blurb {
    display: none;
  }
  .tab {
    padding: 0.35rem 0.45rem;
    font-size: 0.82rem;
  } /* keep all four on one line */
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .float-num {
    display: none;
  }
}
