/* ==========================================================================
   Home — hero, identity, worlds, hotbar, progression, server clock.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Hero. One still, one looping video of the same scene laid over it, and a
   scrim that keeps the left column readable without flattening the moonlit
   right side of the frame.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: max(100svh, 40rem);
  padding-top: var(--nav-h);
  isolation: isolate;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.hero__still,
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 62% 40%;
}

/* The video's first frame is the still, so fading it in is invisible. */
.hero__video {
  opacity: 0;
  transition: opacity 1.2s ease;
}

.hero__video.is-playing {
  opacity: 1;
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(5, 8, 15, 0.7) 0%, rgba(5, 8, 15, 0) 22%, rgba(5, 8, 15, 0) 55%, var(--night-950) 100%),
    linear-gradient(90deg, rgba(5, 8, 15, 0.86) 0%, rgba(5, 8, 15, 0.5) 42%, rgba(5, 8, 15, 0.08) 75%);
}

/* The two live cards: Discord above the game server it belongs to. */
.hero__live {
  display: grid;
  gap: var(--s-3);
  width: 100%;
  max-width: 30rem;
}

.hero__inner {
  flex: 1;
  display: grid;
  align-content: center;
  gap: var(--s-7);
  padding-block: var(--s-7) var(--s-9);
}

.hero__title {
  margin: 0 0 var(--s-5);
}

.hero__title img {
  width: min(86vw, 34rem);
  /* Lifts the wordmark off the water without a visible box. */
  filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.55));
}

.hero__lede {
  max-width: 33rem;
  margin-bottom: var(--s-6);
  color: var(--ink);
  font-size: var(--text-xl);
  font-weight: 500;
  line-height: 1.4;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.7);
}

.hero .eyebrow {
  margin-bottom: var(--s-5);
}

/* One entrance, staggered top to bottom, so the logo lands first. */
@keyframes hero-in {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: none; }
}

.hero__in {
  animation: hero-in 800ms var(--ease-out) both;
  animation-delay: calc(120ms + var(--i, 0) * 110ms);
}

.hero__scroll {
  position: absolute;
  left: 50%;
  bottom: var(--s-5);
  display: none;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink-mute);
  font-size: var(--text-xs);
  text-decoration: none;
  transform: translateX(-50%);
}

.hero__scroll:hover {
  color: var(--oasis-lime);
}

@keyframes nudge {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(5px); }
}

.hero__scroll .icon {
  animation: nudge 1.8s steps(3) infinite;
}

@media (min-width: 960px) {
  .hero__inner {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: end;
    align-content: center;
  }

  .hero__live {
    justify-self: end;
  }

  .hero__scroll {
    display: flex;
  }
}

@media (max-width: 520px) {
  .hero .btn-row .btn {
    width: 100%;
  }

  .server__address {
    flex-direction: column;
    gap: var(--s-3);
  }

  .server__ip {
    min-height: 2.75rem;
  }
}

/* --------------------------------------------------------------------------
   Identity
   -------------------------------------------------------------------------- */

.identity__grid {
  display: grid;
  gap: var(--s-6);
  margin-bottom: var(--s-8);
}

.identity__body > * + * {
  margin-top: var(--s-4);
}

.identity__body .lede {
  margin-top: 0;
  max-width: none;
}

@media (min-width: 900px) {
  .identity__grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-8);
    align-items: start;
  }
}

/* Cells are separated by the grid gap showing the edge colour through, so
   the dividers stay correct at every column count without per-cell rules. */
.statbar {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  padding: 1px;
  --block-fill: var(--line);
}

.statbar .stat {
  padding: var(--s-5);
  background: var(--night-900);
}

.statbar .stat__num {
  background: var(--oasis-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@media (min-width: 640px) {
  .statbar { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 1100px) {
  .statbar { grid-template-columns: repeat(6, 1fr); }
}

/* --------------------------------------------------------------------------
   Worlds — each card carries one block face from its world, drawn on the
   game's own 8×8 grid and set in an inventory slot. The four colours of
   each face come from --px-a…d on the card.
   -------------------------------------------------------------------------- */

.worlds__list {
  display: grid;
  gap: var(--s-4);
}

.world {
  padding: var(--s-5);
  --block-fill: var(--night-800);
}

.world p:not(.world__tag) {
  margin-top: var(--s-3);
  font-size: var(--text-sm);
}

.world__tag {
  margin-bottom: var(--s-2);
  color: var(--ink-mute);
  font-size: var(--text-xs);
}

.world--nether .world__tag { color: var(--nether); }
.world--end .world__tag { color: var(--end); }

.pixel {
  width: 4rem;
  height: 4rem;
  margin-bottom: var(--s-5);
  padding: var(--s-2);
  background: var(--night-950);
  box-shadow: inset 2px 2px 0 rgba(0, 0, 0, 0.6), inset -2px -2px 0 rgba(150, 190, 255, 0.14);
  transition: transform var(--t-base) var(--ease-out);
}

.pixel__a { fill: var(--px-a); }
.pixel__b { fill: var(--px-b); }
.pixel__c { fill: var(--px-c); }
.pixel__d { fill: var(--px-d); }

.world:hover .pixel {
  transform: translateY(-4px);
}

@media (min-width: 640px) {
  .worlds__list { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1040px) {
  .worlds__list { grid-template-columns: repeat(4, 1fr); }
}

/* --------------------------------------------------------------------------
   Map teaser — one link to the live map, showing a real tile of the world.
   The tile is twice as tall as it is wide (colour above, height data below),
   so the window onto it is never taller than it is wide.
   -------------------------------------------------------------------------- */

.maptease {
  display: grid;
  margin-top: var(--s-5);
  color: var(--ink-soft);
  text-decoration: none;
}

/* The chart grid is what shows if the tile cannot be fetched. */
.maptease__view {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background:
    linear-gradient(var(--line) 1px, transparent 1px) 0 0 / 32px 32px,
    linear-gradient(90deg, var(--line) 1px, transparent 1px) 0 0 / 32px 32px,
    var(--night-950);
}

.maptease__tile {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  max-width: none;
  height: auto;
  image-rendering: pixelated;
  transition: transform var(--t-slow) var(--ease-out);
}

/* Fades the terrain into the card on the side the copy sits. */
.maptease__view::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(14, 22, 35, 0) 50%, var(--night-800) 100%);
}

.maptease__copy {
  display: grid;
  align-content: center;
  justify-items: start;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5) var(--s-5);
}

.maptease .eyebrow {
  margin-bottom: 0;
}

.maptease__title {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  transition: color var(--t-fast);
}

.maptease__text {
  max-width: 30rem;
  font-size: var(--text-sm);
}

.maptease__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3) var(--s-5);
  margin-top: var(--s-2);
}

.maptease:hover {
  --block-edge: var(--algo-sky);
  color: var(--ink-soft);
}

.maptease:hover .maptease__title {
  color: var(--algo-sky);
}

.maptease:hover .maptease__tile {
  transform: scale(1.04);
}

.maptease:hover .more .icon {
  transform: translateX(4px);
}

@media (min-width: 860px) {
  .maptease {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  }

  .maptease__view {
    order: 2;
    aspect-ratio: auto;
    min-height: 19rem;
  }

  .maptease__view::after {
    background: linear-gradient(90deg, var(--night-800) 0%, rgba(14, 22, 35, 0) 45%);
  }

  .maptease__copy {
    padding: var(--s-6);
  }
}

/* --------------------------------------------------------------------------
   Hotbar — the feature switcher, built as the game's own nine-slot hotbar.
   A real tablist: arrow keys move between slots, and 1–9 select directly.
   -------------------------------------------------------------------------- */

.hotbar-wrap {
  display: grid;
  gap: var(--s-4);
}

.hotbar {
  display: flex;
  width: fit-content;
  max-width: 100%;
  padding: 4px;
  background: var(--night-950);
  box-shadow: 0 0 0 1px var(--line-strong);
  overflow-x: auto;
  scrollbar-width: none;
}

.hotbar::-webkit-scrollbar {
  display: none;
}

.hotbar__slot {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: clamp(3rem, 9.4vw, 4.25rem);
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  background: var(--night-700);
  /* The bevel of an inventory slot: dark top-left, light bottom-right. */
  box-shadow: inset 2px 2px 0 rgba(0, 0, 0, 0.55), inset -2px -2px 0 rgba(150, 190, 255, 0.14);
  color: var(--ink-mute);
  cursor: pointer;
  transition: color var(--t-fast), background var(--t-fast);
}

.hotbar__slot + .hotbar__slot {
  margin-left: 4px;
}

/* Items wait dimmed in their slots; the one in hand is lit and lifted. */
.hotbar__slot .item {
  opacity: 0.7;
  filter: saturate(0.8);
  transition: opacity var(--t-fast), filter var(--t-fast), transform var(--t-base) var(--ease-out);
}

.hotbar__slot:hover {
  color: var(--ink);
  background: var(--night-600);
}

.hotbar__slot:hover .item {
  opacity: 0.9;
  filter: none;
}

.hotbar__slot[aria-selected="true"] .item {
  opacity: 1;
  filter: none;
  transform: translateY(-2px);
}

/* The selected slot gets the game's thick white selector frame. */
.hotbar__slot[aria-selected="true"] {
  background: var(--night-600);
  color: var(--oasis-lime);
  outline: 3px solid var(--ink);
  outline-offset: 1px;
  z-index: 1;
}

.hotbar__slot:focus-visible {
  outline: 3px solid var(--algo-sky);
  outline-offset: 1px;
  z-index: 2;
}

/* Sits over the item's corner the way a stack count does. */
.hotbar__key {
  position: absolute;
  right: 5px;
  bottom: 3px;
  color: var(--ink-soft);
  font-size: 0.75rem;
  line-height: 1;
  text-shadow: 1px 1px 0 var(--night-950);
}

/* Once the slots reach full size there is room for the item at 3×. */
@media (min-width: 760px) {
  .hotbar__slot .item {
    width: var(--item-3x);
    height: var(--item-3x);
  }
}

.hotbar__hint {
  display: none;
  color: var(--ink-mute);
  font-size: var(--text-xs);
}

@media (hover: hover) and (pointer: fine) {
  .js .hotbar__hint { display: block; }
}

/* On phones all nine slots share the width, so none hides off-screen. */
@media (max-width: 640px) {
  .hotbar {
    width: 100%;
  }

  .hotbar__slot {
    flex: 1;
    width: auto;
    min-width: 0;
  }

  .hotbar__slot + .hotbar__slot {
    margin-left: 3px;
  }

  /* Slots are fluid here, so the item follows them instead of a fixed step. */
  .hotbar__slot .item {
    width: 66%;
    height: auto;
    aspect-ratio: 1;
  }

  .hotbar__key {
    right: 3px;
    bottom: 2px;
    font-size: 0.625rem;
  }
}

.stage {
  --block-fill: var(--night-900);
}

.stage__panel {
  display: grid;
}

.stage__panel:focus-visible {
  outline-offset: -5px;
}

/* Panels carry no hidden attribute in the markup, so without JS all nine are
   readable, stacked. With JS, this rule hides the rest from the first paint
   until home.js takes over and manages [hidden] itself. */
.js [data-hotbar]:not([data-ready]) .stage__panel:not(:first-child) {
  display: none;
}

.no-js .hotbar,
.no-js .hotbar__hint {
  display: none;
}

.stage__panel + .stage__panel {
  border-top: 1px solid var(--line);
}

.stage__img {
  width: 100%;
  height: 100%;
  min-height: 14rem;
  object-fit: cover;
}

.stage__copy {
  display: grid;
  align-content: center;
  justify-items: start;
  gap: var(--s-4);
  padding: clamp(1.5rem, 4vw, 3rem);
}

.stage__copy h3 {
  font-size: var(--text-2xl);
}

@keyframes stage-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

.js .stage__panel:not([hidden]) .stage__copy > * {
  animation: stage-in 420ms var(--ease-out) both;
}

.js .stage__panel:not([hidden]) .stage__copy > :nth-child(2) { animation-delay: 50ms; }
.js .stage__panel:not([hidden]) .stage__copy > :nth-child(3) { animation-delay: 100ms; }
.js .stage__panel:not([hidden]) .stage__copy > :nth-child(4) { animation-delay: 150ms; }
.js .stage__panel:not([hidden]) .stage__copy > :nth-child(5) { animation-delay: 200ms; }

@keyframes stage-img {
  from { opacity: 0; transform: scale(1.04); }
  to { opacity: 1; transform: none; }
}

.js .stage__panel:not([hidden]) .stage__img {
  animation: stage-img 600ms var(--ease-out) both;
}

@media (min-width: 900px) {
  .stage__panel {
    grid-template-columns: 1.05fr 1fr;
    min-height: 27rem;
  }
}

/* --------------------------------------------------------------------------
   Progression — skill bars drawn as the game's segmented XP bar.
   -------------------------------------------------------------------------- */

.progress__grid {
  display: grid;
  gap: var(--s-7);
}

.xp {
  display: grid;
  gap: var(--s-5);
}

.xp__title {
  margin-bottom: var(--s-2);
  color: var(--ink-mute);
  font-size: var(--text-xs);
}

.xp__row {
  display: grid;
  grid-template-columns: 6.5rem 1fr;
  align-items: center;
  gap: var(--s-4);
  padding-block: 0.3rem;
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 500;
}

.xp__bar {
  position: relative;
  height: 10px;
  background: var(--night-950);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6);
  overflow: hidden;
}

.xp__bar i {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, #d5f56a 0%, var(--oasis-lime) 45%, var(--oasis-deep) 100%);
  transform-origin: left;
}

/* Segment notches, as on the in-game bar. */
.xp__bar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(90deg, transparent 0 calc(10% - 2px), rgba(5, 8, 15, 0.75) calc(10% - 2px) 10%);
}

.js [data-reveal] .xp__bar i {
  transform: scaleX(0);
  transition: transform 900ms var(--ease-out);
  transition-delay: calc(200ms + var(--i, 0) * 60ms);
}

.js [data-reveal].is-in .xp__bar i {
  transform: none;
}

.xp__cap {
  color: var(--oasis-lime);
  font-size: var(--text-xs);
  text-align: right;
}

.loop h3 {
  margin-bottom: var(--s-4);
  color: var(--ink-mute);
  font-family: var(--font-hud);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.loop__list {
  display: grid;
  gap: var(--s-4);
}

.loop__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-4);
  padding: var(--s-4);
  background: var(--night-800);
  border-left: 3px solid var(--coin);
}

.loop__item p {
  margin-top: var(--s-1);
  font-size: var(--text-sm);
}

.loop__coin {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  background: var(--night-950);
  box-shadow: inset 2px 2px 0 rgba(0, 0, 0, 0.6), inset -2px -2px 0 rgba(150, 190, 255, 0.14);
  color: var(--coin);
  font-size: var(--text-lg);
}

@media (min-width: 960px) {
  .progress__grid {
    grid-template-columns: 1.15fr 1fr;
    gap: var(--s-8);
    align-items: start;
  }
}

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] .xp__bar i {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Server clock — recurring events, keyed by interval.
   -------------------------------------------------------------------------- */

.clock {
  border-top: 1px solid var(--line-strong);
}

.clock__row {
  display: grid;
  gap: var(--s-2) var(--s-6);
  padding-block: var(--s-5);
  border-bottom: 1px solid var(--line);
  transition: background var(--t-base);
}

.clock__row:hover {
  background: linear-gradient(90deg, rgba(47, 155, 240, 0.07), transparent 70%);
}

.clock__when {
  color: var(--algo-sky);
  font-size: var(--text-sm);
}

.clock__row h3 {
  margin-bottom: var(--s-1);
}

.clock__row p {
  max-width: 40rem;
}

@media (min-width: 760px) {
  .clock__row {
    grid-template-columns: 12rem 1fr;
    align-items: baseline;
    padding-inline: var(--s-4);
  }
}

/* --------------------------------------------------------------------------
   Community cards and closing CTA
   -------------------------------------------------------------------------- */

.live {
  margin-block: var(--s-4) var(--s-5);
  color: var(--ink-mute);
  font-size: var(--text-xs);
}

.quick {
  display: grid;
  gap: var(--s-3);
  justify-content: center;
  margin-top: var(--s-6);
  color: var(--ink);
  font-weight: 500;
  text-align: left;
}

.quick li {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
}

.quick .hud {
  color: var(--oasis-lime);
  font-size: var(--text-sm);
}

@media (min-width: 860px) {
  .quick {
    grid-auto-flow: column;
    gap: var(--s-7);
  }
}
