/* ============================================================================
   Mobile and tablet
   ----------------------------------------------------------------------------
   The site already had a mobile story - the nav collapses into a sheet, the
   footer stacks, the hotbar shrinks - so this is not a rebuild. It closes the
   gaps that were left, and every rule here exists because of a specific way the
   layout broke or a specific thing a touch device does differently.

   Loaded last so it can correct earlier rules without either file having to
   know about the other.
   ============================================================================ */

/* ---------------------------------------------------------------- foundations
   Three things every touch layout needs and none of which were present. */
html {
  /* iOS inflates text in portrait unless told not to, which silently breaks
     any layout tuned at a specific size - text grows, the container does not. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* A hard stop on sideways scroll, on BOTH html and body.
 *
 * body alone is not enough, and the reason is worth recording: the nav sheet is
 * position:fixed and parked off-screen with translateX(100%) when closed, so it
 * sits one full viewport to the right. A fixed element is positioned against the
 * viewport rather than the body, so `overflow-x` on body never clipped it - and
 * measuring the live page confirmed it, with scrollWidth exactly twice the
 * viewport at every single width. The whole site was horizontally draggable on
 * any screen narrow enough to get the sheet.
 *
 * Clipping on the root element is what actually stops it. `clip` rather than
 * `hidden` because hidden would turn the root into a scroll container and break
 * position:sticky on the topbar. */
html, body {
  overflow-x: clip;
  max-width: 100%;
}

/* Notched and rounded phones. Without this the topbar and footer run under the
   status bar and the home indicator. Zero on every device that has no notch. */
.topbar { padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }
.footer { padding-bottom: calc(var(--gap-lg) + env(safe-area-inset-bottom)); }
.hotbar { padding-bottom: env(safe-area-inset-bottom); }

/* ---------------------------------------------------------------- grid safety
   `minmax(300px, 1fr)` does NOT shrink below 300px. auto-fit drops to a single
   column, but that column stays 300px wide - so on a 360px phone with padding
   the card is wider than its container and pushes the page sideways. Wrapping
   the floor in min() lets the track collapse to the container when it has to,
   which is the whole fix and changes nothing on a desktop. */
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }
.stats   { grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); }

/* Anything that can carry a long unbroken string - an IP, a command, a URL -
   has to be allowed to wrap or it sets the page's minimum width by itself. */
.ipbar__value, .cmd__name, code, kbd {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Wide content scrolls inside its own box rather than widening the page. */
.loot, .table-scroll, pre {
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ---------------------------------------------------------------- touch input
   Two things a mouse does that a finger cannot. */
@media (hover: none) {
  /* Hover styles either never fire or, worse, stick after a tap until you tap
     elsewhere - so the card you just left stays lit. Bind the same treatment to
     :active instead, which is what a tap actually produces. */
  .mc-btn:hover, .card:hover, .nav__item:hover, .hotbar__slot:hover { transform: none; }
  .mc-btn:active { transform: translateY(1px); }
  .card:active { border-color: var(--grass); }

  /* The grey flash Safari and Chrome draw over a tapped element, which reads as
     a rendering glitch on a dark theme. */
  a, button, .mc-btn, .card, .hotbar__slot, .nav__item {
    -webkit-tap-highlight-color: transparent;
  }
}

/* Anything tappable gets a real target. 44px is the smallest reliable one. */
@media (pointer: coarse) {
  .mc-btn, .nav__item, .hotbar__slot, .footer__links a, .topbar__search {
    min-height: 44px;
  }
  .footer__links a { display: inline-flex; align-items: center; }
}

/* ---------------------------------------------------------------- tablet
   The nav sheet used to appear at 860px, but there are eleven top-level items.
   Even at the reduced 0.8rem they need roughly 830px before the logo and the
   search box are counted, so between 860 and 1080 the bar was overflowing or
   crushing itself. The sheet now starts at 1024, which covers every tablet in
   portrait and most in landscape. */
@media (max-width: 1024px) {
  .nav__toggle { display: block; }
  .nav {
    position: fixed; inset: 68px 0 0; margin: 0;
    flex-direction: column; gap: 0; align-content: start;
    background: var(--bedrock); padding: var(--gap-md);
    transform: translateX(100%); transition: transform 0.3s var(--ease);
    overflow-y: auto;
    padding-bottom: calc(var(--gap-xl) + env(safe-area-inset-bottom));
  }
  .nav.is-open { transform: none; }
  .nav__item {
    width: 100%; padding: 15px 12px; font-size: 1rem;
    border-bottom: 1px solid var(--stone);
  }
  .nav__item.is-active { background: var(--stone); }
}

/* While the sheet is open the page behind it must not scroll, or a swipe moves
   the wrong thing and closing it leaves you somewhere you did not choose. */
body:has(.nav.is-open) { overflow: hidden; }

/* Tablets have room for two columns but not the three or four a desktop gets,
   and auto-fit alone will happily give a 900px tablet four cramped cards. */
@media (min-width: 641px) and (max-width: 1024px) {
  .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer__inner { grid-template-columns: 1fr 1fr; }
}

/* ---------------------------------------------------------------- phone
   Type scales down, everything becomes one column, and the hero stops trying
   to be a full-height cinematic. */
@media (max-width: 640px) {
  :root { --gap-2xl: 56px; --gap-xl: 40px; --gap-lg: 24px; }

  /* Fluid rather than stepped: a fixed mobile size is always wrong on one of
     the 320-430px range's ends. */
  .hero__title { font-size: clamp(2.4rem, 13vw, 4rem); line-height: 1.05; }
  .section__title { font-size: clamp(1.6rem, 7vw, 2.2rem); }
  .hero__lede { font-size: 1rem; }

  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  .footer__links { grid-template-columns: 1fr; }

  /* The buttons stack full-width, which is both easier to hit and stops a
     three-button row from setting a minimum width the screen cannot meet. */
  .hero__cta { flex-direction: column; align-items: stretch; }
  .hero__cta .mc-btn { width: 100%; justify-content: center; }

  /* A two-column row with a 120px fixed first column leaves ~180px for the item
     name on a small phone, which truncates most of them. Stack instead. */
  .loot__row { grid-template-columns: 1fr; gap: 4px; }
  .note { grid-template-columns: 1fr; }

  /* Horizontal strip rather than a wrapped block - it is a toolbar, and a
     toolbar that reflows into three rows stops reading as one. */
  .hotbar { overflow-x: auto; justify-content: flex-start; scrollbar-width: none; }
  .hotbar::-webkit-scrollbar { display: none; }
}

@media (max-width: 380px) {
  /* The narrowest phones still in use. Only the things that actually clip. */
  :root { --slot-size: 46px; }
  .hotbar__slot { width: 44px; height: 44px; }
  .topbar__brand span { font-size: 0.9rem; }
  .ipbar__value { font-size: 0.78rem; }
}

/* ---------------------------------------------------------------- landscape
   A phone on its side has ~380px of height. A hero sized in vh eats all of it
   and the page looks empty until you scroll, which reads as a broken page. */
@media (max-height: 480px) and (orientation: landscape) {
  .hero { min-height: auto; }
  .hero__inner { padding-block: var(--gap-lg); }
  .hero__title { font-size: clamp(2rem, 7vh, 3rem); }
  .nav { inset: 56px 0 0; }
}

/* ---------------------------------------------------------------- the canvas
   The hero backdrop generates a voxel world in WebGL. On a desktop that costs
   about a second; on a mid-range phone it is the most expensive thing on the
   page, on the battery as well as the clock, and it sits behind text that is
   perfectly readable without it.

   Hidden rather than merely shrunk, and hidden in CSS so it applies even if the
   script has already started - hero.js reads the same breakpoint and skips
   building the world at all, so this is the visual half of one decision. */
@media (max-width: 640px), (pointer: coarse) and (max-width: 900px) {
  #hero-canvas { display: none; }
  .hero {
    background:
      linear-gradient(180deg, rgba(11, 15, 20, 0.35), rgba(11, 15, 20, 0.9)),
      linear-gradient(160deg, #3f6ea8 0%, #5a8fc4 45%, #7fae57 45%, #4f7a3a 100%);
  }
}

/* ---------------------------------------------------------------- print
   Not a device, but the same class of problem: the fixed chrome is meaningless
   on paper and the dark theme wastes an entire cartridge. */
@media print {
  .topbar, .hotbar, .footer, #hero-canvas, .motion-toggle { display: none; }
  body { background: #fff; color: #000; }
  .card { border: 1px solid #999; break-inside: avoid; }
}
