/* ==========================================================================
   azerothsurvivors.games — site.css
   --------------------------------------------------------------------------
   One stylesheet, no framework, no build step. Organised as:

     01  Design tokens
     02  Reset & base
     03  Typography
     04  Ornaments (filigree, runes, corner brackets)
     05  Buttons
     06  Panels & cards
     07  Header & navigation
     08  Hero
     09  The game player (facade, iframe, loading, fallback, fullscreen)
     10  Sections: features, steps, gallery, video, classes, zones, community
     11  FAQ (native <details>) & tables
     12  Footer
     13  Motion, focus, print

   The look is deliberate: gold on a violet-black night, stone-set panels with
   bevelled gold frames, rune marks instead of bullets. It is meant to read as
   the same world as the game it frames, which is drawn in the same palette —
   the embed should look like a window into the game, not a widget on a blog.
   ========================================================================== */

/* ── 01  Design tokens ───────────────────────────────────────────────────── */
:root {
  /* night sky → stone */
  --ink-950: #06050b;
  --ink-900: #0a0813;
  --ink-850: #100c1c;
  --ink-800: #161125;
  --ink-750: #1d1730;
  --ink-700: #241d3b;
  --stone-600: #33294f;
  --stone-500: #453a63;

  /* gold, the whole point */
  --gold-100: #fff6dc;
  --gold-200: #f7e6b4;
  --gold-300: #eed58c;
  --gold-400: #ddbc66;
  --gold-500: #c39c3f;
  --gold-600: #9a7a2c;
  --gold-700: #6d5620;
  --gold-900: #33260e;

  /* parchment text */
  --text: #e9e0cc;
  --text-soft: #c9bfa8;
  --text-dim: #9a907c;
  --text-faint: #6f6757;

  /* faction / element accents */
  --horde: #a8232b;
  --horde-lit: #d8434b;
  --alliance: #2f6fb5;
  --alliance-lit: #58a0e0;
  --arcane: #8360cf;
  --arcane-lit: #a98ce8;
  --nature: #3f9d6a;
  --nature-lit: #63c48d;
  --ember: #e0702a;
  --ember-lit: #f59a4e;
  --frost: #4fb3c9;

  /* semantic */
  --ok: #4fbf85;
  --warn: #e2a53c;
  --bad: #e0605c;

  --radius-sm: 4px;
  --radius: 8px;
  --radius-lg: 14px;

  --shadow-panel: 0 18px 44px -22px rgba(0, 0, 0, 0.95), 0 2px 0 0 rgba(255, 255, 255, 0.03) inset;
  --shadow-lift: 0 26px 60px -26px rgba(0, 0, 0, 1), 0 0 0 1px rgba(221, 188, 102, 0.14);
  --glow-gold: 0 0 0 1px rgba(221, 188, 102, 0.35), 0 0 28px -6px rgba(221, 188, 102, 0.35);

  --font-display: 'Cinzel', 'Palatino Linotype', 'Book Antiqua', Georgia, serif;
  --font-body: 'Alegreya Sans', 'Segoe UI', system-ui, -apple-system, sans-serif;

  --wrap: 1180px;
  --wrap-narrow: 860px;
  --gutter: clamp(1rem, 4vw, 2.5rem);

  --header-h: 66px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ── 02  Reset & base ────────────────────────────────────────────────────── */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 16px);
}

body {
  margin: 0;
  background-color: var(--ink-950);
  color: var(--text);
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.075rem);
  line-height: 1.68;
  font-weight: 400;
  overflow-x: hidden;
  /* A night sky over stone: two soft auras, no image request. */
  background-image:
    radial-gradient(900px 520px at 12% -8%, rgba(131, 96, 207, 0.16), transparent 62%),
    radial-gradient(760px 460px at 92% 4%, rgba(194, 156, 63, 0.13), transparent 60%),
    radial-gradient(1100px 700px at 50% 120%, rgba(47, 111, 181, 0.1), transparent 65%);
  background-attachment: fixed;
}

img,
svg,
video,
iframe,
canvas {
  display: block;
  max-width: 100%;
}

/* The inlined icon sprite is a <svg> like any other, so it needs excluding
   from the rule above or it renders as an empty block at the top of <body>. */
svg.sprite,
.sprite {
  display: none !important;
}

img {
  height: auto;
}

a {
  color: var(--gold-300);
  text-decoration-color: rgba(238, 213, 140, 0.35);
  text-underline-offset: 3px;
}

a:hover {
  color: var(--gold-100);
  text-decoration-color: currentColor;
}

p {
  margin: 0 0 1.05em;
}

ul,
ol {
  margin: 0 0 1.05em;
  padding-left: 1.15em;
}

li {
  margin-bottom: 0.4em;
}

li::marker {
  color: var(--gold-500);
}

hr {
  border: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold-700), transparent);
  margin: 2.6rem 0;
}

::selection {
  background: rgba(194, 156, 63, 0.35);
  color: #fff;
}

/* Skip link — keyboard users get past the nav in one tab. */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--gold-400);
  color: var(--ink-950);
  padding: 0.6rem 1.1rem;
  font: 700 0.95rem/1 var(--font-body);
  border-radius: 0 0 var(--radius) 0;
}

.skip:focus {
  left: 0;
}

/* ── 03  Typography ──────────────────────────────────────────────────────── */
h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: 0.005em;
  margin: 0 0 0.5em;
  color: var(--gold-200);
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.1rem, 1.35rem + 3.5vw, 4rem);
  letter-spacing: -0.005em;
  color: #fff;
}

h2 {
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.15rem);
}

h3 {
  font-size: clamp(1.15rem, 1rem + 0.6vw, 1.42rem);
  color: var(--gold-300);
}

h4 {
  font-size: 1.06rem;
  color: var(--gold-300);
  letter-spacing: 0.02em;
}

/* Small-caps rune label used above every section title. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold-400);
  margin: 0 0 0.9rem;
}

.eyebrow::before {
  content: '';
  width: 7px;
  height: 7px;
  background: var(--gold-500);
  transform: rotate(45deg);
  box-shadow: 0 0 10px 1px rgba(195, 156, 63, 0.7);
  flex: none;
}

.lede {
  font-size: clamp(1.08rem, 1rem + 0.5vw, 1.3rem);
  color: var(--text-soft);
  line-height: 1.62;
}

.section-title {
  max-width: 46ch;
}

.section-title p {
  font-family: var(--font-body);
  color: var(--text-dim);
  font-size: 1.02rem;
  font-weight: 400;
  letter-spacing: 0;
  margin: 0.6rem 0 0;
}

.gold {
  background: linear-gradient(180deg, var(--gold-100) 8%, var(--gold-400) 52%, var(--gold-600) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.nowrap {
  white-space: nowrap;
}

/* ── 04  Ornaments ───────────────────────────────────────────────────────── */
/* Section divider: a filigree line with a rune diamond in the middle. Pure CSS
   so it costs no request and scales with the text. */
.filigree {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin: 0 0 2rem;
  color: var(--gold-600);
}

.filigree::before,
.filigree::after {
  content: '';
  height: 1px;
  flex: 1;
  background: linear-gradient(90deg, transparent, currentColor 40%, currentColor 60%, transparent);
  opacity: 0.75;
}

.filigree > span {
  display: flex;
  gap: 0.45rem;
  align-items: center;
}

.filigree i {
  display: block;
  width: 8px;
  height: 8px;
  background: currentColor;
  transform: rotate(45deg);
}

.filigree i:nth-child(2) {
  width: 11px;
  height: 11px;
  background: var(--gold-400);
  box-shadow: 0 0 12px 1px rgba(221, 188, 102, 0.6);
}

/* Corner brackets: four L-shaped gold corners drawn with gradients. */
.cornered {
  position: relative;
}

.cornered::before,
.cornered::after {
  content: '';
  position: absolute;
  width: 22px;
  height: 22px;
  pointer-events: none;
  border: 1px solid var(--gold-500);
  opacity: 0.85;
}

.cornered::before {
  top: -1px;
  left: -1px;
  border-right: 0;
  border-bottom: 0;
}

.cornered::after {
  bottom: -1px;
  right: -1px;
  border-left: 0;
  border-top: 0;
}

/* ── 05  Buttons ─────────────────────────────────────────────────────────── */
.btn {
  --btn-bg: linear-gradient(180deg, var(--gold-300) 0%, var(--gold-500) 55%, var(--gold-600) 100%);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.78rem 1.5rem;
  border: 1px solid var(--gold-700);
  border-radius: var(--radius-sm);
  background: var(--btn-bg);
  color: #2a1f06;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.94rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  box-shadow:
    0 1px 0 0 rgba(255, 253, 240, 0.6) inset,
    0 -2px 0 0 rgba(90, 62, 12, 0.55) inset,
    0 10px 22px -12px rgba(0, 0, 0, 0.95);
  transition: transform 0.16s var(--ease), box-shadow 0.16s var(--ease), filter 0.16s var(--ease);
}

.btn:hover {
  filter: brightness(1.07);
  transform: translateY(-1px);
  color: #2a1f06;
}

.btn:active {
  transform: translateY(1px);
  box-shadow: 0 2px 0 0 rgba(255, 253, 240, 0.35) inset, 0 4px 12px -8px rgba(0, 0, 0, 0.9);
}

.btn svg {
  width: 1.15em;
  height: 1.15em;
  flex: none;
}

.btn--ghost {
  --btn-bg: linear-gradient(180deg, rgba(68, 55, 100, 0.55), rgba(20, 16, 32, 0.75));
  border-color: rgba(221, 188, 102, 0.42);
  color: var(--gold-200);
}

.btn--ghost:hover {
  color: var(--gold-100);
  border-color: var(--gold-400);
}

.btn--lg {
  padding: 0.95rem 1.9rem;
  font-size: 1.02rem;
}

.btn--sm {
  padding: 0.5rem 0.9rem;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

/* ── 06  Panels & cards ──────────────────────────────────────────────────── */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap--narrow {
  max-width: var(--wrap-narrow);
}

.section {
  padding-block: clamp(2.8rem, 6vw, 5rem);
  position: relative;
}

.panel {
  position: relative;
  background:
    linear-gradient(180deg, rgba(36, 29, 59, 0.72), rgba(12, 9, 22, 0.86)),
    radial-gradient(600px 200px at 50% 0%, rgba(195, 156, 63, 0.09), transparent 70%);
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  box-shadow: var(--shadow-panel);
  padding: clamp(1.2rem, 3vw, 2rem);
}

/* The bevelled gold frame used on the player and on hero panels. */
.panel--gilded {
  border: 1px solid var(--gold-700);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.8),
    0 0 0 2px rgba(109, 86, 32, 0.55),
    var(--shadow-panel);
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 1.35rem 1.3rem 1.45rem;
  background: linear-gradient(180deg, rgba(36, 29, 59, 0.6), rgba(10, 8, 19, 0.75));
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  box-shadow: var(--shadow-panel);
  transition: transform 0.2s var(--ease), border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.card:hover {
  transform: translateY(-3px);
  border-color: rgba(221, 188, 102, 0.5);
  box-shadow: var(--shadow-lift);
}

.card h3 {
  margin: 0;
  font-size: 1.08rem;
}

.card p {
  margin: 0;
  color: var(--text-dim);
  font-size: 0.97rem;
  line-height: 1.58;
}

.card__icon {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: radial-gradient(circle at 50% 20%, rgba(195, 156, 63, 0.3), rgba(10, 8, 19, 0.6) 70%);
  border: 1px solid var(--gold-700);
  color: var(--gold-300);
  margin-bottom: 0.35rem;
}

.card__icon svg {
  width: 26px;
  height: 26px;
}

.grid {
  display: grid;
  gap: 1.1rem;
}

.grid--2 {
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

.grid--3 {
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

.grid--4 {
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
}

/* `auto-fit` counts columns from the container width, which turns six feature
   cards into a ragged 4 + 2 on a wide screen. This variant pins the count so a
   six-card set reads as 3 + 3 and a three-card set never stretches to four. */
.grid--thirds {
  grid-template-columns: 1fr;
}

@media (min-width: 720px) {
  .grid--thirds {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1000px) {
  .grid--thirds {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* A stat strip: big gold numbers in a row, like a character sheet. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 1px;
  background: var(--stone-600);
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  overflow: hidden;
}

.stats div {
  background: linear-gradient(180deg, rgba(29, 23, 48, 0.9), rgba(10, 8, 19, 0.95));
  padding: 1rem 1.1rem;
}

.stats b {
  display: block;
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.1;
  color: var(--gold-300);
}

.stats span {
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-family: var(--font-display);
}

/* Callout for anything the reader must not miss (WebGPU, capacity, IP). */
.callout {
  display: flex;
  gap: 0.95rem;
  padding: 1.05rem 1.2rem;
  border-radius: var(--radius);
  border: 1px solid rgba(226, 165, 60, 0.4);
  background: linear-gradient(180deg, rgba(226, 165, 60, 0.11), rgba(226, 165, 60, 0.04));
  font-size: 0.97rem;
}

.callout svg {
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--warn);
  margin-top: 0.15rem;
}

.callout p:last-child {
  margin-bottom: 0;
}

.callout--info {
  border-color: rgba(79, 179, 201, 0.4);
  background: linear-gradient(180deg, rgba(79, 179, 201, 0.1), rgba(79, 179, 201, 0.03));
}

.callout--info svg {
  color: var(--frost);
}

/* ── 07  Header & navigation ─────────────────────────────────────────────── */
.header {
  position: sticky;
  top: 0;
  z-index: 60;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: linear-gradient(180deg, rgba(6, 5, 11, 0.95), rgba(6, 5, 11, 0.78));
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(109, 86, 32, 0.5);
}

.header::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(221, 188, 102, 0.55), transparent);
}

.header__inner {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  align-items: center;
  gap: 1rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--gold-200);
  margin-right: auto;
}

.brand svg {
  width: 30px;
  height: 30px;
  color: var(--gold-400);
  filter: drop-shadow(0 0 8px rgba(195, 156, 63, 0.4));
}

.brand b {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
}

.brand small {
  display: block;
  font-family: var(--font-body);
  font-size: 0.63rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-top: 1px;
}

.nav {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.nav a {
  padding: 0.5rem 0.7rem;
  border-radius: var(--radius-sm);
  font-size: 0.93rem;
  font-weight: 500;
  color: var(--text-soft);
  text-decoration: none;
  white-space: nowrap;
}

.nav a:hover,
.nav a[aria-current='page'] {
  color: var(--gold-100);
  background: rgba(221, 188, 102, 0.1);
}

@media (max-width: 860px) {
  .nav {
    display: none;
  }
}

/* ── 08  Hero ────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  padding-block: clamp(2rem, 5vw, 3.4rem) clamp(1.6rem, 4vw, 2.6rem);
  text-align: center;
  overflow: hidden;
}

/* Ember motes: a handful of CSS dots drifting upward. Cosmetic only, and it
   stops completely under prefers-reduced-motion (see §13). */
.hero__motes {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.hero__motes i {
  position: absolute;
  bottom: -12px;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--gold-300);
  box-shadow: 0 0 10px 1px rgba(238, 213, 140, 0.75);
  opacity: 0;
  animation: mote 14s linear infinite;
}

.hero__motes i:nth-child(1) { left: 8%;  animation-delay: 0s;   animation-duration: 15s; }
.hero__motes i:nth-child(2) { left: 21%; animation-delay: 2.4s; animation-duration: 18s; }
.hero__motes i:nth-child(3) { left: 34%; animation-delay: 5.1s; animation-duration: 13s; }
.hero__motes i:nth-child(4) { left: 47%; animation-delay: 1.2s; animation-duration: 20s; }
.hero__motes i:nth-child(5) { left: 61%; animation-delay: 7.6s; animation-duration: 16s; }
.hero__motes i:nth-child(6) { left: 74%; animation-delay: 3.3s; animation-duration: 19s; }
.hero__motes i:nth-child(7) { left: 86%; animation-delay: 9.4s; animation-duration: 14s; }
.hero__motes i:nth-child(8) { left: 94%; animation-delay: 6.2s; animation-duration: 21s; }

@keyframes mote {
  0%   { transform: translateY(0) scale(0.7); opacity: 0; }
  12%  { opacity: 0.85; }
  70%  { opacity: 0.5; }
  100% { transform: translateY(-78vh) scale(1.15); opacity: 0; }
}

.hero__title {
  margin: 0 0 0.35rem;
  /* No text-shadow here on purpose: the title is filled with a clipped
     gradient (see .gold), and a text-shadow paints on top of that fill, which
     turns bright gold into olive. A filter applies after painting, so the
     shadow lands where it belongs — behind the glyph. */
  filter: drop-shadow(0 3px 16px rgba(0, 0, 0, 0.9)) drop-shadow(0 0 42px rgba(195, 156, 63, 0.2));
}

/* The keyword sits in the H1; this is the human-readable promise under it. */
.hero__lede {
  max-width: 62ch;
  margin: 0.5rem auto 1.6rem;
}

.hero__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.45rem 1.35rem;
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.9rem;
  color: var(--text-dim);
}

.hero__meta li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
}

.hero__meta svg {
  width: 16px;
  height: 16px;
  color: var(--gold-500);
  flex: none;
}

/* ── 09  The game player ─────────────────────────────────────────────────── */
.player {
  margin-top: clamp(1.6rem, 4vw, 2.6rem);
  text-align: left;
}

/* Window chrome — the frame is presented as a game window, not a video. */
.player__chrome {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0.75rem 0.55rem 0.9rem;
  background: linear-gradient(180deg, #2a2242, #150f28);
  border: 1px solid var(--gold-700);
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
}

.player__gems {
  display: flex;
  gap: 6px;
  flex: none;
}

.player__gems i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.6);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25) inset;
}

.player__gems i:nth-child(1) { background: radial-gradient(circle at 35% 30%, #ff8a86, var(--horde)); }
.player__gems i:nth-child(2) { background: radial-gradient(circle at 35% 30%, #ffe6a3, var(--gold-500)); }
.player__gems i:nth-child(3) { background: radial-gradient(circle at 35% 30%, #8ce0b1, var(--nature)); }

.player__url {
  flex: 1;
  min-width: 0;
  font-family: var(--font-body);
  font-size: 0.8rem;
  color: var(--text-faint);
  letter-spacing: 0.03em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  background: rgba(6, 5, 11, 0.6);
  border: 1px solid rgba(109, 86, 32, 0.45);
}

.player__url b {
  color: var(--gold-400);
  font-weight: 500;
}

.player__tools {
  display: flex;
  gap: 0.4rem;
  flex: none;
}

.player__tool {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(109, 86, 32, 0.6);
  background: linear-gradient(180deg, rgba(68, 55, 100, 0.6), rgba(10, 8, 19, 0.8));
  color: var(--gold-300);
  cursor: pointer;
  text-decoration: none;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}

.player__tool:hover {
  border-color: var(--gold-400);
  color: var(--gold-100);
}

.player__tool svg {
  width: 15px;
  height: 15px;
}

/* The stage: fixed 16:9 box so nothing reflows when the game loads. */
.stage {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #000;
  border: 1px solid var(--gold-700);
  border-top: 0;
  border-radius: 0 0 var(--radius) var(--radius);
  overflow: hidden;
  box-shadow: 0 0 0 2px rgba(109, 86, 32, 0.45), 0 30px 70px -30px rgba(0, 0, 0, 1);
}

.stage[data-state='live'] {
  border-color: var(--gold-500);
}

.stage > iframe,
.stage > .stage__layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Facade: the poster + play button. This is what the crawler and a first-time
   visitor see, and it is why the homepage can stay fast while the game itself
   is 137 MiB. */
.stage__layer {
  display: grid;
  z-index: 2;
}

.facade {
  place-items: center;
  cursor: pointer;
  background: #05040a;
  border: 0;
  padding: 0;
  color: inherit;
  font: inherit;
  text-align: center;
}

.facade[hidden] {
  display: none;
}

.facade img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.8;
  transition: opacity 0.4s var(--ease), transform 0.6s var(--ease);
}

.facade:hover img {
  opacity: 0.92;
  transform: scale(1.015);
}

.facade::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Dark enough for the gold label to stay legible, light enough that the
     game behind it is obviously a game. */
  background: radial-gradient(circle at 50% 46%, rgba(6, 5, 11, 0.04), rgba(6, 5, 11, 0.66) 80%),
    linear-gradient(180deg, rgba(6, 5, 11, 0.34), rgba(6, 5, 11, 0.12) 40%, rgba(6, 5, 11, 0.5));
}

.facade__inner {
  position: relative;
  z-index: 3;
  display: grid;
  justify-items: center;
  gap: 0.85rem;
  padding: 1rem;
  max-width: 34ch;
}

.play-orb {
  position: relative;
  width: clamp(72px, 11vw, 104px);
  height: clamp(72px, 11vw, 104px);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 25%, var(--gold-200), var(--gold-500) 55%, var(--gold-700));
  border: 2px solid var(--gold-600);
  box-shadow:
    0 0 0 6px rgba(6, 5, 11, 0.55),
    0 0 0 8px rgba(221, 188, 102, 0.35),
    0 16px 40px -12px rgba(0, 0, 0, 0.9),
    0 0 60px -6px rgba(221, 188, 102, 0.45);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}

.facade:hover .play-orb,
.facade:focus-visible .play-orb {
  transform: scale(1.06);
  box-shadow:
    0 0 0 6px rgba(6, 5, 11, 0.55),
    0 0 0 8px rgba(238, 213, 140, 0.5),
    0 20px 46px -12px rgba(0, 0, 0, 0.95),
    0 0 78px -4px rgba(238, 213, 140, 0.6);
}

/* A slow rune ring turning behind the orb — the only "loading" flourish that
   is always running, so it is cheap and purely decorative. */
.play-orb::before {
  content: '';
  position: absolute;
  inset: -16px;
  border-radius: 50%;
  border: 1px dashed rgba(238, 213, 140, 0.4);
  animation: spin 26s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.play-orb svg {
  width: 40%;
  height: 40%;
  color: #2a1f06;
  margin-left: 6%;
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, 0.35));
}

.facade__label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.05rem, 2.4vw, 1.5rem);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-100);
  text-shadow: 0 3px 18px rgba(0, 0, 0, 0.95);
}

.facade__note {
  font-size: 0.88rem;
  color: var(--text-soft);
  line-height: 1.5;
}

.facade__badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.28rem 0.7rem;
  border-radius: 999px;
  border: 1px solid rgba(221, 188, 102, 0.4);
  background: rgba(6, 5, 11, 0.72);
  font-size: 0.76rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-family: var(--font-display);
  color: var(--gold-300);
}

.facade__badge[data-gpu='ok'] { border-color: rgba(79, 191, 133, 0.5); color: var(--ok); }
.facade__badge[data-gpu='no'] { border-color: rgba(224, 96, 92, 0.5); color: var(--bad); }
.facade__badge[data-gpu='check'] { border-color: rgba(226, 165, 60, 0.5); color: var(--warn); }

/* A 16:9 stage is only ~219 px tall on a 390 px phone, which is not enough
   room for the orb, the label, the note and the GPU badge. Drop the prose and
   keep the two things that matter: the promise and the compatibility state. */
@media (max-width: 560px) {
  .facade__note {
    display: none;
  }

  .play-orb {
    width: 64px;
    height: 64px;
  }

  .play-orb::before {
    inset: -10px;
  }

  .facade__label {
    font-size: 1rem;
    letter-spacing: 0.1em;
  }

  .facade__inner {
    gap: 0.5rem;
  }
}

/* Loading state */
.loading {
  place-items: center;
  background: radial-gradient(circle at 50% 40%, #14101f, #05040a 70%);
  z-index: 4;
}

.loading[hidden] {
  display: none;
}

.loading__inner {
  width: min(420px, 82%);
  text-align: center;
}

.loading__rune {
  width: 54px;
  height: 54px;
  margin: 0 auto 1rem;
  color: var(--gold-400);
  animation: spin 3.4s linear infinite;
}

.loading__title {
  font-family: var(--font-display);
  font-size: 1.05rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-200);
  margin: 0 0 0.35rem;
}

.loading__step {
  font-size: 0.92rem;
  color: var(--text-dim);
  margin: 0 0 1.05rem;
  min-height: 2.6em;
}

.bar {
  position: relative;
  height: 8px;
  border-radius: 999px;
  background: rgba(6, 5, 11, 0.85);
  border: 1px solid var(--gold-900);
  overflow: hidden;
}

.bar > i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--gold-600), var(--gold-300), var(--gold-500));
  box-shadow: 0 0 14px 1px rgba(221, 188, 102, 0.5);
  transition: width 0.8s linear;
}

.loading__hint {
  margin: 0.9rem 0 0;
  font-size: 0.86rem;
  color: var(--text-faint);
}

.loading__hint b {
  color: var(--gold-400);
  font-weight: 500;
}

/* Fallback state (no WebGPU / capacity / never started) */
.fallback {
  place-items: center;
  z-index: 4;
  background: radial-gradient(circle at 50% 40%, #1a1226, #05040a 72%);
  padding: 1.2rem;
}

.fallback[hidden] {
  display: none;
}

.fallback__inner {
  width: min(560px, 92%);
  text-align: center;
}

.fallback__icon {
  width: 44px;
  height: 44px;
  margin: 0 auto 0.7rem;
  color: var(--warn);
}

.fallback__title {
  margin: 0 0 0.4rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
  line-height: 1.2;
  color: var(--gold-200);
}

.fallback p {
  color: var(--text-soft);
  font-size: 0.95rem;
  margin: 0 0 1rem;
}

.fallback .btn-row {
  justify-content: center;
}

/* Fullscreen: the stage fills the screen and the chrome floats over it. */
.stage:fullscreen,
.stage:-webkit-full-screen {
  aspect-ratio: auto;
  height: 100%;
  border: 0;
  border-radius: 0;
}

.stage:fullscreen .stage__exit,
.stage:-webkit-full-screen .stage__exit {
  display: inline-flex;
}

.stage__exit {
  display: none;
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 20;
}

/* Under the stage: the client's own control scheme, in game-UI style. */
.controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.1rem;
  margin: 0.9rem 0 0;
  padding: 0.75rem 1rem;
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(29, 23, 48, 0.6), rgba(10, 8, 19, 0.6));
  font-size: 0.88rem;
  color: var(--text-dim);
  list-style: none;
}

.controls li {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
}

kbd {
  display: inline-block;
  min-width: 1.7em;
  padding: 0.15em 0.42em;
  border-radius: 4px;
  border: 1px solid var(--gold-700);
  border-bottom-width: 2px;
  background: linear-gradient(180deg, #2c2445, #14101f);
  color: var(--gold-200);
  font-family: var(--font-display);
  font-size: 0.82em;
  font-weight: 600;
  text-align: center;
}

/* ── 10  Sections ────────────────────────────────────────────────────────── */
.steps {
  counter-reset: step;
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.9rem;
}

.steps li {
  counter-increment: step;
  position: relative;
  padding: 1.05rem 1.2rem 1.05rem 3.6rem;
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  background: linear-gradient(90deg, rgba(36, 29, 59, 0.5), rgba(10, 8, 19, 0.6));
  margin: 0;
}

.steps li::before {
  content: counter(step);
  position: absolute;
  left: 1rem;
  top: 1.05rem;
  width: 1.85rem;
  height: 1.85rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--gold-600);
  background: radial-gradient(circle at 50% 25%, rgba(238, 213, 140, 0.35), rgba(10, 8, 19, 0.9));
  color: var(--gold-200);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.92rem;
}

.steps b {
  color: var(--gold-200);
  font-weight: 700;
}

/* Screenshot gallery */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1rem;
}

.shot {
  position: relative;
  display: block;
  padding: 0;
  border: 1px solid var(--gold-700);
  border-radius: var(--radius);
  background: #05040a;
  overflow: hidden;
  cursor: zoom-in;
  box-shadow: var(--shadow-panel);
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.shot:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
}

.shot img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  opacity: 0.92;
  transition: opacity 0.2s var(--ease);
}

.shot:hover img {
  opacity: 1;
}

.shot figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 1.4rem 0.85rem 0.7rem;
  font-size: 0.855rem;
  color: var(--gold-200);
  background: linear-gradient(180deg, transparent, rgba(6, 5, 11, 0.92));
  text-align: left;
  font-family: var(--font-display);
  letter-spacing: 0.04em;
}

/* Lightbox — native <dialog>, so focus trapping and Esc come for free. */
.lightbox {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: min(1180px, 94vw);
  max-height: 94vh;
}

.lightbox::backdrop {
  background: rgba(3, 2, 8, 0.88);
  backdrop-filter: blur(4px);
}

.lightbox img {
  width: 100%;
  border: 1px solid var(--gold-600);
  border-radius: var(--radius);
  box-shadow: 0 40px 90px -30px #000;
}

.lightbox p {
  margin: 0.7rem 0 0;
  color: var(--text-soft);
  font-size: 0.92rem;
  text-align: center;
}

.lightbox__close {
  position: absolute;
  top: -14px;
  right: -14px;
  width: 36px;
  height: 36px;
}

/* Video facade (lazy YouTube: nothing loads from Google until clicked) */
.video {
  position: relative;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--gold-700);
  border-radius: var(--radius);
  overflow: hidden;
  background: #05040a;
}

.video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Class / zone chips */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0;
  margin: 0;
  list-style: none;
}

.chips li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  padding: 0.42rem 0.85rem;
  border-radius: 999px;
  border: 1px solid var(--stone-600);
  background: linear-gradient(180deg, rgba(36, 29, 59, 0.55), rgba(10, 8, 19, 0.7));
  font-size: 0.9rem;
  color: var(--text-soft);
}

.chips svg {
  width: 15px;
  height: 15px;
  flex: none;
}

.chips li[data-role='melee'] svg { color: var(--horde-lit); }
.chips li[data-role='caster'] svg { color: var(--arcane-lit); }
.chips li[data-role='hybrid'] svg { color: var(--nature-lit); }

/* ── Class roster & boss clock ─────────────────────────────────────────────
   The class icons are the game's own, cut from its picker into a 3x3 sprite
   (scripts/art.mjs). Using the real icons is both the honest choice — this is
   the artwork the player sees when choosing — and a free one: one 12 KiB file
   covers all nine, and no per-icon requests. The homepage shows them as a
   visual index and deliberately does NOT repeat the guide's stat table. */
.class-roster {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: 0.5rem;
  list-style: none;
  padding: 0;
  margin: 0 0 1.2rem;
}

.class-roster li {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(36, 29, 59, 0.55), rgba(10, 8, 19, 0.72));
  font-family: var(--font-display);
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  color: var(--gold-200);
}

/* --s is the rendered icon size and the sheet is exactly 3x3 cells of it, so a
   single variable rescales both the sprite and every position. */
.class-icon {
  --s: 34px;
  width: var(--s);
  height: var(--s);
  flex: none;
  border-radius: 5px;
  background-image: url(/assets/img/class-icons.webp);
  background-size: calc(var(--s) * 3) calc(var(--s) * 3);
  background-repeat: no-repeat;
  box-shadow: 0 0 0 1px var(--gold-700), 0 2px 6px -2px #000;
}

.class-icon--warrior { background-position: 0 0; }
.class-icon--paladin { background-position: calc(var(--s) * -1) 0; }
.class-icon--hunter { background-position: calc(var(--s) * -2) 0; }
.class-icon--rogue { background-position: 0 calc(var(--s) * -1); }
.class-icon--priest { background-position: calc(var(--s) * -1) calc(var(--s) * -1); }
.class-icon--shaman { background-position: calc(var(--s) * -2) calc(var(--s) * -1); }
.class-icon--mage { background-position: 0 calc(var(--s) * -2); }
.class-icon--warlock { background-position: calc(var(--s) * -1) calc(var(--s) * -2); }
.class-icon--druid { background-position: calc(var(--s) * -2) calc(var(--s) * -2); }

/* The guide's class table gets the same icon at a smaller size, so the two
   pages share one asset but not one sentence. */
.class-cell {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  white-space: nowrap;
}

.class-cell .class-icon {
  --s: 26px;
}

/* The zone timer as a row of gold pills: the shape of a run in one line, and
   no table for the guide's zone section to compete with. */
.boss-clock {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 1.1rem 0 0;
}

.boss-clock span {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--gold-700);
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(195, 156, 63, 0.14), rgba(10, 8, 19, 0.6));
  font-size: 0.85rem;
  color: var(--text-soft);
}

.boss-clock b {
  font-family: var(--font-display);
  color: var(--gold-300);
  letter-spacing: 0.04em;
}

.boss-clock .is-final {
  border-color: var(--gold-500);
  background: linear-gradient(180deg, rgba(195, 156, 63, 0.26), rgba(10, 8, 19, 0.6));
  color: var(--gold-100);
}

/* Requirements: three scannable answers instead of a second copy of the
   guide's browser-support table. */
.req-list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.req-list li {
  position: relative;
  margin: 0;
  padding-left: 1.9rem;
  color: var(--text-soft);
}

.req-list li::before {
  content: '';
  position: absolute;
  left: 0.5rem;
  top: 0.55em;
  width: 8px;
  height: 8px;
  background: var(--gold-500);
  transform: rotate(45deg);
  box-shadow: 0 0 10px 1px rgba(195, 156, 63, 0.6);
}

/* Two-column "aside" layout: copy on the left, panel on the right. */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(1.2rem, 4vw, 2.6rem);
  align-items: start;
}

@media (max-width: 900px) {
  .split {
    grid-template-columns: 1fr;
  }
}

/* Community links */
.links {
  display: grid;
  gap: 0.7rem;
  padding: 0;
  margin: 0;
  list-style: none;
}

.links li {
  margin: 0;
}

.links a {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(36, 29, 59, 0.5), rgba(10, 8, 19, 0.65));
  text-decoration: none;
  color: var(--text);
  transition: border-color 0.15s var(--ease), transform 0.15s var(--ease);
}

.links a:hover {
  border-color: rgba(221, 188, 102, 0.5);
  transform: translateX(3px);
  color: var(--gold-100);
}

.links svg {
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--gold-400);
}

.links b {
  display: block;
  font-family: var(--font-display);
  font-size: 0.96rem;
  letter-spacing: 0.03em;
  color: var(--gold-200);
}

.links small {
  color: var(--text-faint);
  font-size: 0.86rem;
}

/* ── 11  FAQ & tables ────────────────────────────────────────────────────── */
.faq {
  display: grid;
  gap: 0.6rem;
}

.faq details {
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(36, 29, 59, 0.42), rgba(10, 8, 19, 0.6));
  overflow: hidden;
}

.faq details[open] {
  border-color: rgba(221, 188, 102, 0.42);
}

.faq summary {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.95rem 1.1rem;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--gold-200);
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: '+';
  margin-left: auto;
  font-size: 1.35rem;
  line-height: 1;
  color: var(--gold-500);
  transition: transform 0.2s var(--ease);
}

.faq details[open] summary::after {
  content: '–';
}

.faq summary:hover {
  color: var(--gold-100);
  background: rgba(221, 188, 102, 0.06);
}

.faq__a {
  padding: 0 1.1rem 1.05rem;
  color: var(--text-soft);
  font-size: 0.985rem;
}

.faq__a p:last-child {
  margin-bottom: 0;
}

table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 1.2rem;
  font-size: 0.94rem;
}

caption {
  caption-side: bottom;
  padding-top: 0.55rem;
  color: var(--text-faint);
  font-size: 0.84rem;
  text-align: left;
}

th,
td {
  padding: 0.65rem 0.8rem;
  text-align: left;
  border-bottom: 1px solid rgba(69, 58, 99, 0.55);
  vertical-align: top;
}

thead th {
  font-family: var(--font-display);
  font-size: 0.78rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--gold-400);
  border-bottom-color: var(--gold-700);
  background: rgba(36, 29, 59, 0.4);
}

tbody tr:hover {
  background: rgba(221, 188, 102, 0.045);
}

td b,
th b {
  color: var(--gold-200);
}

.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Answer-first block: a short, quotable summary an AI answer can lift. */
.answer {
  border-left: 3px solid var(--gold-500);
  padding: 0.2rem 0 0.2rem 1.1rem;
  margin: 0 0 1.4rem;
  color: var(--text-soft);
  font-size: 1.02rem;
}

/* Table of contents on the guide page */
.toc {
  padding: 1.1rem 1.3rem;
  border: 1px solid var(--stone-600);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(36, 29, 59, 0.5), rgba(10, 8, 19, 0.6));
}

.toc h2 {
  font-size: 0.86rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-400);
  margin: 0 0 0.6rem;
}

.toc ol {
  columns: 2;
  column-gap: 1.6rem;
  margin: 0;
  padding-left: 1.2rem;
  font-size: 0.94rem;
}

@media (max-width: 640px) {
  .toc ol {
    columns: 1;
  }
}

/* ── 12  Footer ──────────────────────────────────────────────────────────── */
.footer {
  margin-top: clamp(2.4rem, 6vw, 4rem);
  border-top: 1px solid rgba(109, 86, 32, 0.5);
  background: linear-gradient(180deg, rgba(6, 5, 11, 0.6), rgba(6, 5, 11, 0.95));
  padding-block: 2.6rem 1.6rem;
  font-size: 0.92rem;
}

.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(auto-fit, minmax(140px, 1fr));
  gap: 1.8rem;
  margin-bottom: 2rem;
}

.footer h2 {
  font-size: 0.8rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-400);
  margin: 0 0 0.7rem;
}

.footer ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.footer li {
  margin-bottom: 0.45rem;
}

.footer a {
  color: var(--text-soft);
  text-decoration: none;
}

.footer a:hover {
  color: var(--gold-100);
  text-decoration: underline;
}

.footer__brand p {
  color: var(--text-dim);
  max-width: 44ch;
}

.legal {
  border-top: 1px solid rgba(69, 58, 99, 0.5);
  padding-top: 1.2rem;
  color: var(--text-faint);
  font-size: 0.84rem;
}

.legal p {
  margin: 0 0 0.5rem;
}

.legal a {
  color: var(--text-dim);
}

/* ── 13  Motion, focus, print ────────────────────────────────────────────── */
:focus-visible {
  outline: 2px solid var(--gold-300);
  outline-offset: 3px;
  border-radius: 3px;
}

/* Scroll reveal.
   Deliberately CSS-only and behind @supports: the animation is driven by the
   scroll timeline, so the resting state IS the visible state. A JS-driven
   version (hide with CSS, unhide with an IntersectionObserver) leaves every
   below-the-fold section invisible if the script fails to load or throws —
   an unacceptable failure mode for a page whose job is to be read and ranked.
   Browsers without scroll-driven animations simply render the content, and
   every crawler sees it regardless. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    [data-reveal] {
      animation: reveal-in linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 70%;
    }
  }
}

@keyframes reveal-in {
  from {
    /* An opacity FLOOR, not zero. If the scroll timeline ever fails to advance
       — a stitched screenshot, a print, an unusual scroll container — the
       content is still legible rather than invisible. */
    opacity: 0.4;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

}

@media print {
  .header,
  .footer,
  .player,
  .hero__motes {
    display: none !important;
  }

  body {
    background: #fff;
    color: #111;
  }

  a::after {
    content: ' (' attr(href) ')';
    font-size: 0.85em;
  }
}

/* ==========================================================================
   14  The world layer  (added on top of the base system above)
   --------------------------------------------------------------------------
   Two jobs, and they share one asset:

     · the first screen must show the GAME WORLD, not a black field, so the
       hero gets a sky layer (the client's own key art, blended to violet) and
       a world layer (our gameplay panorama) under a scrim that is heavy where
       the words are and deliberately thin where the world should read;
     · the click-to-play wait must feel designed, so the loading state is a
       five-stage rail (a pip is a fact; a percentage would be a guess), a
       rotating tip in the client's own tradition, an honest elapsed clock and
       a hand-off that DOCKS instead of blocking once the client draws its own
       progress screen.

   One image, one key art, reused at different crops and opacities — the whole
   page becomes one landscape you scroll through for 87 KiB. Rules that must
   hold: section art never exceeds --art-a (0.09, ceiling 0.14) or body copy
   loses AA; nothing here animates a property that is wrong at rest; every
   effect degrades to a static, legible page if it is unsupported.
   ========================================================================== */

/* ── 14.1  Tokens ───────────────────────────────────────────────────────── */
:root {
  --art-a: 0.09;              /* section art opacity, ceiling 0.14 */
  --art-blur: 2px;
  --scrim-hero-copy: 0.74;    /* the copy-bed radial: the contrast floor */
  --world-h: clamp(300px, 46vh, 540px);
  --handoff-at: 20;           /* seconds; where the client draws its own bar */
}

/* The background auras move to a fixed layer. `background-attachment: fixed` is
   ignored on iOS and repaints the whole gradient stack on every scroll frame
   elsewhere; one fixed, composited layer looks identical and costs nothing. */
body {
  background-image: none;
  background-color: var(--ink-950);
}

body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(900px 520px at 12% -8%, rgba(131, 96, 207, 0.16), transparent 62%),
    radial-gradient(760px 460px at 92% 4%, rgba(194, 156, 63, 0.13), transparent 60%),
    radial-gradient(1100px 700px at 50% 118%, rgba(47, 111, 181, 0.1), transparent 65%);
}

/* ── 14.2  .gold can never make the headline invisible ──────────────────── */
.gold {
  color: var(--gold-300);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .gold {
    background: linear-gradient(180deg, var(--gold-100) 8%, var(--gold-300) 46%, var(--gold-500) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    /* A clipped gradient is a BACKGROUND, while text-shadow belongs to the
       text, so the shadow is composited over the fill and darkens it. Legibility
       comes from the scrim and the copy bed instead; a filter is the only way to
       get a shadow behind a clipped fill. */
    text-shadow: none;
  }
}

/* ── 14.3  World texture: one image, many crops, always under the words ─── */
.section[data-art] {
  position: relative;
  isolation: isolate;
}

.section[data-art]::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: var(--art);
  background-size: cover;
  background-repeat: no-repeat;
  background-position: var(--art-pos, 50% 50%);
  opacity: var(--art-a);
  filter: blur(var(--art-blur)) saturate(0.5) brightness(0.8) hue-rotate(-16deg);
  -webkit-mask-image: var(--art-mask, linear-gradient(180deg, transparent 0%, #000 22%, #000 78%, transparent 100%));
  mask-image: var(--art-mask, linear-gradient(180deg, transparent 0%, #000 22%, #000 78%, transparent 100%));
}

.section[data-art] > .wrap {
  position: relative;
  z-index: 1;
}

.section[data-art='world'] {
  --art: url('/assets/img/hero-world.webp');
}

.section[data-art='keyart'] {
  --art: url('/assets/img/art-keyart.webp');
}

/* The key art is warm sepia; laid over violet it reads brown. Taking its
   luminance and the page's own hue is what makes it night art instead. */
.section[data-art='keyart']::before {
  filter: blur(1px) saturate(0.35) contrast(1.06);
  mix-blend-mode: luminosity;
}

.section[data-art-pos='left'] { --art-pos: 18% 62%; }
.section[data-art-pos='sky'] { --art-pos: 80% 30%; }
.section[data-art-pos='floor'] { --art-pos: 50% 82%; }
.section[data-art-pos='forest'] { --art-pos: 12% 44%; }
.section[data-art-pos='light'] { --art-pos: 88% 70%; --art-a: 0.06; }

/* ── 14.4  Hero: sky, world, scrim, copy bed ────────────────────────────── */
.hero {
  position: relative;
  isolation: isolate;      /* contains the sky's blend mode */
  overflow: visible;       /* the world band bleeds under the player */
  padding-block: clamp(1.7rem, 3.4vw, 2.6rem) clamp(1.8rem, 4vw, 3rem);
  background:
    radial-gradient(1100px 520px at 50% -12%, rgba(131, 96, 207, 0.24), transparent 66%),
    radial-gradient(760px 420px at 6% 4%, rgba(168, 35, 43, 0.1), transparent 62%),
    radial-gradient(820px 460px at 96% 2%, rgba(194, 156, 63, 0.13), transparent 62%),
    linear-gradient(180deg, #0b0916 0%, var(--ink-950) 76%);
}

.hero__sky {
  position: absolute;
  inset: 0 0 auto 0;
  height: clamp(340px, 58vh, 600px);
  z-index: -2;
  overflow: hidden;
  pointer-events: none;
}

.hero__sky img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 62% 14%;   /* the warrior's helm, right of the headline */
  filter: contrast(1.1) brightness(1.04) saturate(0.3);
  opacity: 0.34;
  mix-blend-mode: luminosity;
  -webkit-mask-image: radial-gradient(124% 78% at 58% 4%, #000 0%, rgba(0, 0, 0, 0.55) 46%, transparent 78%);
  mask-image: radial-gradient(124% 78% at 58% 4%, #000 0%, rgba(0, 0, 0, 0.55) 46%, transparent 78%);
}

.hero__world {
  position: absolute;
  inset: auto 0 -84px 0;
  height: calc(var(--world-h) + 84px);
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}

.hero__world img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 78%;   /* horizon low: the grass reads as ground */
  /* Sunny Elwynn green walked into the site's own gold, then dimmed to night. */
  filter: saturate(0.58) brightness(0.64) contrast(1.08) hue-rotate(-16deg);
  opacity: 0.85;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.3) 20%, #000 52%, #000 86%, rgba(0, 0, 0, 0.5) 100%);
  mask-image: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.3) 20%, #000 52%, #000 86%, rgba(0, 0, 0, 0.5) 100%);
}

/* The scrim: heavy where the sentence is, thin where the world is. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(6, 5, 11, 0.88) 0%, rgba(6, 5, 11, 0.74) 24%, rgba(6, 5, 11, 0.44) 44%, rgba(6, 5, 11, 0.1) 64%, rgba(6, 5, 11, 0) 78%, rgba(6, 5, 11, 0.55) 100%),
    radial-gradient(150% 96% at 50% 30%, transparent 30%, rgba(6, 5, 11, 0.66) 100%);
}

.hero > .wrap {
  position: relative;
  z-index: 1;
}

.hero__copy {
  position: relative;
}

/* A radial, so it never reads as a box, and it guarantees the contrast floor
   whatever frame the capture happens to be. */
.hero__copy::before {
  content: '';
  position: absolute;
  inset: -1.6rem -3rem -1.2rem;
  border-radius: 50%;
  background: radial-gradient(62% 76% at 50% 44%, rgba(6, 5, 11, var(--scrim-hero-copy)), rgba(6, 5, 11, 0) 72%);
  pointer-events: none;
}

.hero__copy > * {
  position: relative;
}

.hero__title {
  margin: 0 0 0.4rem;
  filter: drop-shadow(0 3px 16px rgba(0, 0, 0, 0.92)) drop-shadow(0 0 46px rgba(195, 156, 63, 0.22));
}

.hero__lede {
  max-width: 46ch;
  margin: 0.55rem auto 1.5rem;
}

.btn-row--center {
  justify-content: center;
}

/* The facts strip lives under the player, where it answers a question the
   visitor has already started asking, instead of crowding the first screen. */
.specbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
  margin: 0.7rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.875rem;
  color: var(--text-dim);
}

.specbar li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
}

.specbar svg {
  width: 15px;
  height: 15px;
  color: var(--gold-500);
  flex: none;
}

/* ── 14.5  Click-to-load: instant feedback, then a designed wait ────────── */
.stage[data-state='arming'] .facade img {
  opacity: 0.35;
  filter: blur(3px) brightness(0.6);
  transition: opacity 0.18s var(--ease), filter 0.18s var(--ease);
}

.stage[data-state='arming'] .play-orb {
  transform: scale(0.86);
}

.play-orb::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid rgba(238, 213, 140, 0.9);
  opacity: 0;
  pointer-events: none;
}

.stage[data-state='arming'] .play-orb::after {
  animation: shock 0.55s var(--ease) forwards;
}

@keyframes shock {
  from { transform: scale(1); opacity: 0.9; }
  to { transform: scale(2.6); opacity: 0; }
}

.stage[data-state='arming'] .facade {
  cursor: progress;
}

.loading {
  place-items: center;
  z-index: 4;
  background: radial-gradient(circle at 50% 34%, rgba(36, 29, 59, 0.9), rgba(5, 4, 10, 0.97) 68%), var(--ink-950);
  transition: background-color 0.6s var(--ease), opacity 0.6s var(--ease);
}

.loading__inner {
  width: min(460px, 86%);
  text-align: center;
  display: grid;
  gap: 0.9rem;
}

.loading__seal {
  position: relative;
  width: 76px;
  height: 76px;
  margin: 0 auto 0.2rem;
  display: grid;
  place-items: center;
}

.loading__rings {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
}

.loading__rings circle {
  stroke: rgba(109, 86, 32, 0.5);
  stroke-width: 2;
}

.loading__rings .arc,
.loading__rings .arc2 {
  stroke: var(--gold-400);
  stroke-linecap: round;
  stroke-dasharray: 78 250;
  transform-origin: 60px 60px;
  animation: spin 2.6s linear infinite;
}

.loading__rings .arc2 {
  stroke: var(--gold-600);
  stroke-dasharray: 46 210;
  animation-duration: 4.1s;
  animation-direction: reverse;
}

.loading__rune {
  width: 30px;
  height: 30px;
  color: var(--gold-300);
}

.loading__title {
  font-family: var(--font-display);
  font-size: 1.02rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-200);
  margin: 0 0 0.3rem;
}

.loading__step {
  font-size: 0.93rem;
  color: var(--text-soft);
  margin: 0;
  min-height: 2.6em;
}

/* Five pips, not a percentage: a pip is a fact we can stand behind, a
   percentage would be a guess about a document we cannot read. */
.rail {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail li {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 0.34rem;
  font-family: var(--font-display);
  font-size: 0.63rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
  transition: color 0.3s var(--ease);
}

.rail i {
  width: 100%;
  height: 4px;
  border-radius: 999px;
  background: rgba(69, 58, 99, 0.6);
  border: 1px solid rgba(0, 0, 0, 0.6);
  transition: background 0.35s var(--ease), box-shadow 0.35s var(--ease);
}

.rail li[data-on='done'] {
  color: var(--gold-400);
}

.rail li[data-on='done'] i {
  background: linear-gradient(90deg, var(--gold-600), var(--gold-300));
  box-shadow: 0 0 10px 0 rgba(221, 188, 102, 0.45);
}

.rail li[data-on='now'] {
  color: var(--gold-100);
}

.rail li[data-on='now'] i {
  background: linear-gradient(90deg, var(--gold-500), var(--gold-200));
  box-shadow: 0 0 16px 1px rgba(238, 213, 140, 0.6);
  animation: railpulse 1.6s ease-in-out infinite;
}

@keyframes railpulse {
  50% { opacity: 0.55; }
}

.loading__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.3rem 1rem;
  text-align: left;
}

.loading__hint {
  margin: 0;
  font-size: 0.84rem;
  color: var(--text-dim);
  max-width: 34ch;
}

.loading__clock {
  margin: 0;
  font-size: 0.78rem;
  color: var(--text-faint);
  letter-spacing: 0.06em;
  white-space: nowrap;
}

.loading__clock b {
  font-family: var(--font-display);
  color: var(--gold-400);
  font-variant-numeric: tabular-nums;
}

/* The tip line is the client's own tradition — its loading screens carry one —
   and it is the only part of the wait that gives something back. */
.tips {
  border: 1px solid rgba(109, 86, 32, 0.55);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(36, 29, 59, 0.55), rgba(10, 8, 19, 0.7)),
    radial-gradient(280px 90px at 50% 0%, rgba(195, 156, 63, 0.1), transparent 70%);
  padding: 0.7rem 0.95rem 0.8rem;
  text-align: left;
  min-height: 5.4em;
}

.tips__label {
  margin: 0 0 0.25rem;
  font-family: var(--font-display);
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-500);
}

.tips__text {
  margin: 0;
  font-size: 0.9rem;
  color: var(--text-soft);
  line-height: 1.5;
}

.tips__text[data-swap] {
  animation: tipin 0.45s var(--ease);
}

@keyframes tipin {
  from { opacity: 0; transform: translateY(4px); }
}

.loading__actions {
  justify-content: center;
  gap: 0.5rem;
}

/* Hand-off: dock, do not block. From the moment the client draws its own
   progress bar, ours gets out of the way — but keeps the tips coming. */
.loading[data-phase='handoff'] {
  place-items: end start;
  background: transparent;
  pointer-events: none;
}

.loading[data-phase='handoff'] .loading__inner {
  pointer-events: auto;
  width: min(340px, 62%);
  margin: 0 0 14px 14px;
  padding: 0.8rem 0.9rem 0.85rem;
  gap: 0.5rem;
  text-align: left;
  border: 1px solid rgba(221, 188, 102, 0.28);
  border-radius: var(--radius);
  background: rgba(8, 6, 15, 0.82);
  backdrop-filter: blur(6px);
}

.loading[data-phase='handoff'] .loading__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.loading[data-phase='handoff'] .loading__seal {
  width: 22px;
  height: 22px;
  margin: 0;
}

.loading[data-phase='handoff'] .loading__rings {
  display: none;
}

.loading[data-phase='handoff'] .loading__rune {
  width: 20px;
  height: 20px;
}

.loading[data-phase='handoff'] .loading__title {
  font-size: 0.72rem;
  margin: 0;
}

.loading[data-phase='handoff'] .loading__step,
.loading[data-phase='handoff'] .rail,
.loading[data-phase='handoff'] .bar {
  display: none;
}

.loading[data-phase='handoff'] .loading__hint {
  font-size: 0.78rem;
  max-width: none;
}

.loading[data-phase='handoff'] .tips {
  min-height: 0;
  padding: 0.55rem 0.7rem 0.6rem;
}

.loading[data-phase='handoff'] .tips__text {
  font-size: 0.82rem;
}

.loading[data-phase='handoff'] .loading__actions {
  justify-content: flex-start;
}

/* Four stats in the default three-column grid leave two cells empty, which is
   the clearest "this is a template" tell on the page. Two columns fill it
   exactly, and the wider cells suit the short values. */
.stats--quad {
  grid-template-columns: repeat(2, 1fr);
}

/* ── 14.6  Class icons: one sprite, nine <img>s, real dimensions ────────── */
.ci {
  inline-size: 26px;
  block-size: 26px;
  object-fit: none;      /* show the sheet at native size, cropped by position */
  border-radius: 5px;
  border: 1px solid rgba(109, 86, 32, 0.75);
  background: #0a0813;
  flex: none;
  vertical-align: -6px;
}

/* Picker order: Warrior Paladin Hunter / Rogue Priest Shaman / Mage Warlock
   Druid, one 64 px cell each on the 192 px sheet. */
.ci[data-r='0'][data-c='0'] { object-position: 0 0; }
.ci[data-r='0'][data-c='1'] { object-position: -64px 0; }
.ci[data-r='0'][data-c='2'] { object-position: -128px 0; }
.ci[data-r='1'][data-c='0'] { object-position: 0 -64px; }
.ci[data-r='1'][data-c='1'] { object-position: -64px -64px; }
.ci[data-r='1'][data-c='2'] { object-position: -128px -64px; }
.ci[data-r='2'][data-c='0'] { object-position: 0 -128px; }
.ci[data-r='2'][data-c='1'] { object-position: -64px -128px; }
.ci[data-r='2'][data-c='2'] { object-position: -128px -128px; }

.class-cell {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  white-space: nowrap;
}

/* Health as a bar, so 245 against 165 is a glance instead of a comparison. */
.hp {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.hp i {
  display: block;
  inline-size: 74px;
  block-size: 5px;
  border-radius: 999px;
  background: rgba(69, 58, 99, 0.55);
  overflow: hidden;
}

.hp i::after {
  content: '';
  display: block;
  block-size: 100%;
  inline-size: calc(var(--hp) / 245 * 100%);
  background: linear-gradient(90deg, #2f7a4d, var(--ok));
}

tr:hover .hp i {
  box-shadow: 0 0 10px -2px rgba(79, 191, 133, 0.6);
}

/* ── 14.7  The roster, and the zone chain ───────────────────────────────── */
.class-roster li {
  justify-content: flex-start;
}

/* Content chips take the card radius, not a pill: pills stay reserved for
   chrome and status. The role stripe replaces nine identical map pins. */
.chips li {
  border-radius: var(--radius);
  border-color: rgba(109, 86, 32, 0.5);
  padding: 0.36rem 0.7rem 0.36rem 0.42rem;
  gap: 0.5rem;
}

.chips li[data-role='melee'] { box-shadow: inset 2px 0 0 var(--horde-lit); }
.chips li[data-role='caster'] { box-shadow: inset 2px 0 0 var(--arcane-lit); }
.chips li[data-role='hybrid'] { box-shadow: inset 2px 0 0 var(--nature-lit); }

.chain {
  position: relative;
  margin: 0.8rem 0 0;
  padding: 0 0 0 1.55rem;
  list-style: none;
  counter-reset: zone;
}

.chain::before {
  content: '';
  position: absolute;
  left: 7px;
  top: 0.55rem;
  bottom: 0.55rem;
  width: 1px;
  background: linear-gradient(180deg, var(--gold-500), rgba(109, 86, 32, 0.25));
}

.chain li {
  counter-increment: zone;
  position: relative;
  margin: 0 0 0.7rem;
  line-height: 1.35;
}

.chain li::before {
  content: counter(zone);
  position: absolute;
  left: -1.55rem;
  top: 0.1rem;
  width: 15px;
  height: 15px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--ink-900);
  border: 1px solid var(--gold-700);
  color: var(--gold-400);
  font: 700 0.6rem/1 var(--font-display);
}

.chain li[data-open]::before {
  border-color: var(--gold-400);
  color: var(--ink-950);
  background: var(--gold-400);
  box-shadow: 0 0 12px -1px rgba(221, 188, 102, 0.7);
}

.chain b {
  display: block;
  color: var(--gold-200);
  font-weight: 500;
  font-size: 0.96rem;
}

.chain small {
  display: block;
  color: var(--text-faint);
  font-size: 0.82rem;
}

.chain li:hover b {
  color: var(--gold-100);
}

/* ── 14.8  Component polish ─────────────────────────────────────────────── */
/* A gold highlight that crosses the plate once on hover. The band lives inside
   the button and is clipped by it: unclipped, the idle -120 % offset painted a
   grey parallelogram next to the button and behind the nav. */
.btn {
  overflow: clip;
}

.btn::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(105deg, transparent 34%, rgba(255, 253, 240, 0.42) 50%, transparent 66%);
  transform: translateX(-120%);
  opacity: 0;
  pointer-events: none;
}

.btn:hover::after {
  opacity: 1;
  animation: sheen 0.7s var(--ease);
}

@keyframes sheen {
  to { transform: translateX(120%); }
}

/* A hairline that draws itself along the top edge of a card. */
.card::before {
  content: '';
  position: absolute;
  inset: -1px -1px auto;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold-400), transparent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}

.card:hover::before,
.card:focus-within::before {
  transform: scaleX(1);
}

@media (min-width: 1000px) {
  .grid--thirds > .card:first-child {
    grid-column: span 2;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: start;
    background: linear-gradient(180deg, rgba(36, 29, 59, 0.55), rgba(10, 8, 19, 0.82)),
      url('/assets/img/hero-world.webp') 60% 70% / cover no-repeat;
  }

  .grid--thirds > .card:first-child .card__icon {
    grid-row: span 2;
  }
}

/* The FAQ marker becomes a chevron that rotates: the same information, told
   with motion instead of a character swap. */
.faq summary {
  padding-left: 1.1rem;
}

.faq summary::after {
  content: none;
}

.faq__chev {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--gold-500);
  transition: transform 0.22s var(--ease), color 0.22s var(--ease);
}

.faq details[open] .faq__chev {
  transform: rotate(90deg);
  color: var(--gold-300);
}

.faq details[open] summary {
  border-bottom: 1px solid rgba(109, 86, 32, 0.4);
  background: rgba(221, 188, 102, 0.05);
}

.faq details[open] {
  box-shadow: inset 3px 0 0 var(--gold-500);
}

/* kbd chips press like keys. */
kbd {
  transition: transform 0.08s var(--ease), border-bottom-width 0.08s var(--ease);
}

kbd:active,
.controls li:active kbd {
  transform: translateY(1px);
  border-bottom-width: 1px;
}

/* Gallery: the frame tightens and the caption lifts. */
.shot img {
  transition: transform 0.35s var(--ease), opacity 0.2s var(--ease);
}

.shot:hover img {
  transform: scale(1.025);
}

.shot figcaption {
  transition: transform 0.25s var(--ease);
}

.shot:hover figcaption {
  transform: translateY(-3px);
}

/* The header gains a scrim once the page has moved. Zero JS, and the resting
   state IS the current appearance, so an unsupported browser sees no change. */
@supports (animation-timeline: scroll()) {
  .header {
    animation: header-tighten linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 140px;
  }
}

@keyframes header-tighten {
  to {
    box-shadow: 0 10px 30px -18px #000;
    border-bottom-color: rgba(221, 188, 102, 0.7);
  }
}

/* Frosted glass over a *scrolling* image re-blurs every frame; the header goes
   opaque instead, and the blur budget is spent on the small static dock. */
.header {
  backdrop-filter: none;
  background: linear-gradient(180deg, rgba(6, 5, 11, 0.97), rgba(6, 5, 11, 0.86));
}

/* More air: the cheapest way for a long page to stop feeling templated. */
.section {
  padding-block: clamp(3.2rem, 6.5vw, 5.6rem);
}

/* The page sinks back into the ground. */
.footer {
  position: relative;
  isolation: isolate;
  padding-block: 2.8rem 1.6rem;
}

.footer::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: url('/assets/img/hero-world.webp') 50% 86% / cover no-repeat;
  opacity: 0.11;
  filter: blur(1.5px) saturate(0.45) brightness(0.75) hue-rotate(-16deg);
  -webkit-mask-image: radial-gradient(120% 100% at 50% 100%, #000, transparent 78%);
  mask-image: radial-gradient(120% 100% at 50% 100%, #000, transparent 78%);
}

/* ── 14.9  Small screens ────────────────────────────────────────────────── */
@media (max-width: 560px) {
  /* The header is the tightest row on the page. At 390 px the crest was being
     flex-shrunk to 3 px (a flex item shrinks below its own width unless told
     not to) and the call to action wrapped onto two lines. */
  .brand {
    gap: 0.45rem;
  }

  .brand svg {
    width: 26px;
    height: 26px;
    flex: none;
    filter: none;
  }

  .brand b {
    font-size: 0.8rem;
    letter-spacing: 0.045em;
  }

  .brand small {
    display: none;
  }

  .header .btn {
    white-space: nowrap;
    padding-inline: 0.85rem;
    font-size: 0.72rem;
    letter-spacing: 0.06em;
  }

  .hero__sky {
    height: 340px;
  }

  .hero__sky img {
    opacity: 0.18;
  }

  .hero__world {
    height: calc(clamp(190px, 28vh, 250px) + 44px);
    inset: auto 0 -44px 0;
  }

  /* A 390 px crop of a 1280 px panorama makes positional variety invisible. */
  .section[data-art]::before {
    background-position: 50% 50%;
    opacity: calc(var(--art-a) * 0.75);
    filter: blur(1px) saturate(0.5) brightness(0.8) hue-rotate(-16deg);
  }

  /* The stage stays 16:9 on purpose: growing it on click would be a ~300 px
     layout shift. The loading UI is a compact stack built to fit inside it. */
  .loading__inner {
    gap: 0.5rem;
    width: min(460px, 90%);
  }

  .loading__seal {
    width: 46px;
    height: 46px;
  }

  .loading__rune {
    width: 20px;
    height: 20px;
  }

  .loading__title {
    font-size: 0.84rem;
  }

  .loading__step {
    font-size: 0.84rem;
    min-height: 2.8em;
  }

  .rail span {
    display: none;
  }

  .tips {
    min-height: 4.6em;
    padding: 0.55rem 0.7rem 0.6rem;
  }

  .tips__text {
    font-size: 0.82rem;
  }

  .loading__actions {
    display: grid;
  }

  .loading__actions .btn {
    width: 100%;
  }

  /* The copy bed's radial bleeds 3rem sideways for the wide screens, which at
     390 px would push the page 32 px wider than the viewport. Keep the contrast
     guarantee, drop the bleed. */
  .hero__copy::before {
    inset: -1.2rem -0.5rem -1rem;
  }

  .loading[data-phase='handoff'] .loading__inner {
    width: min(340px, 100%);
    margin: 0 0 8px 8px;
  }
}

/* The tip rotation is information, not decoration, so it keeps running under
   reduced motion; only the movement is dropped. */
@media (prefers-reduced-motion: reduce) {
  .stage[data-state='arming'] .play-orb::after {
    animation: none;
  }

  .loading[data-phase='handoff'] {
    transition: none;
  }

  .tips__text[data-swap] {
    animation: none;
  }
}
