@font-face {
  font-family: "Prime Display";
  src: url("assets/fonts/anton-v27-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Prime Text";
  src: url("assets/fonts/inter-v20-latin-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Wordmark face. NOTE: this file is a 62-glyph subset - it carries a-z plus
   A C I P T U W and a few digits and symbols, nothing else. The hero wordmark
   is set in lowercase on purpose: this font's lowercase ARE small-cap forms,
   all one uniform height, which is what gives the all-caps look. Archivo Black
   stays in the stack below it as a per-glyph fallback. */
@font-face {
  font-family: "Quadrat Grotesk";
  src: url("assets/fonts/quadrat-grotesk-new-bold.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Archivo Black";
  src: url("assets/fonts/archivo-black-v23-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* The game's own Quadrat (the client's login-form face, 71 capitals: A-Z and the
   Cyrillic alphabet, 7 KB), for the green button's label: it is the lettering the
   original site's FIGHT! button was drawn in. Georgian and Armenian fall through to
   Prime Intl. */
@font-face {
  font-family: "Tanki Quadrat";
  src: url("assets/fonts/quadrat-game.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: dark;
  --page: #04080d;
  --page-blue: #07111c;
  --panel: #0a131e;
  --panel-raised: #101c29;
  --line: rgba(173, 196, 215, 0.18);
  --line-strong: rgba(190, 210, 226, 0.35);
  --text: #f1f4f6;
  --muted: #9aa9b5;
  --blue: #85bfe5;
  --orange: #f59a32;
  --orange-bright: #ffc063;
  --orange-dark: #6c3511;
  --shell: min(1180px, calc(100% - 48px));
  /* Discord's brand blurple, for everything that opens our Discord. */
  --discord: #5865f2;
  --discord-deep: #4752c4;
  --discord-press: #3c45a5;
  --discord-light: #8c95ff;
  /* Headings: one voice (Inter Black, capitals) at two sizes. Display is for the
     page's big statements, title for anything that sits inside a block. */
  --display-size: clamp(3rem, 5vw, 4.8rem);
  --title-size: clamp(1.6rem, 2.5vw, 2.4rem);
  --display-tracking: -0.03em;
  --display-words: 0.05em;
  --hero-parallax: 0px;
}

* {
  box-sizing: border-box;
}

html {
  min-width: 320px;
  /* the pinned bar would cover the top of whatever an anchor jumps to */
  scroll-padding-top: 88px;
  scroll-behavior: smooth;
  scrollbar-color: #263747 var(--page);
}

html {
  overflow-x: clip;
}

/* The page locks while the menu sheet is open (app.js toggles it). */
body.nav-open {
  overflow: hidden;
}

body {
  position: relative;
  min-height: 100vh;
  margin: 0;
  overflow-x: clip;
  background: #03080e;
  color: var(--text);
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
}

/* One night sky behind every section (2026-09-18). It replaced two blurred game
   screenshots (384px and 640px wide, stretched over a full screen: that was the
   pixelation) and a dozen painted "glass streaks" and blobs. Only gradients, so it
   is smooth at any size and painted once. It is taller than the screen and slides
   up by half a screen over the length of the page, slower than the content, so
   you feel the depth as you scroll. The slide is a scroll-driven animation of
   transform: the compositor runs it, no script and no repaint. Browsers without
   scroll timelines, and reduced motion, keep it still. */
body::before {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 0;
  height: 150vh;
  content: "";
  background:
    radial-gradient(ellipse 62% 30% at 50% 0%, rgba(116, 166, 212, 0.2), transparent 72%),
    radial-gradient(ellipse 40% 26% at 0% 36%, rgba(236, 122, 34, 0.15), transparent 72%),
    radial-gradient(ellipse 36% 24% at 100% 26%, rgba(96, 152, 202, 0.11), transparent 72%),
    radial-gradient(ellipse 42% 28% at 100% 66%, rgba(230, 112, 28, 0.13), transparent 72%),
    radial-gradient(ellipse 48% 28% at 16% 90%, rgba(90, 144, 194, 0.12), transparent 72%),
    linear-gradient(180deg, #081320 0%, #050c15 52%, #03070d 100%);
  pointer-events: none;
  will-change: transform;
}

@keyframes sky-drift {
  to { transform: translate3d(0, -50vh, 0); }
}

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    body::before {
      animation: sky-drift linear both;
      animation-timeline: scroll(root block);
    }
  }
}

body > * {
  position: relative;
  z-index: 1;
}

/* Above the footer. The footer's fade starts 140px up, under the last section, and
   is meant to sit behind the page: level with main it painted over the cards and
   drew a seam across the Discord card on phones. */
main {
  position: relative;
  z-index: 2;
  isolation: isolate;
}

a {
  color: inherit;
  text-decoration: none;
}

img {
  display: block;
  max-width: 100%;
}

button,
a {
  -webkit-tap-highlight-color: transparent;
}

button {
  color: inherit;
  font: inherit;
}

:focus-visible {
  outline: 3px solid var(--orange-bright);
  outline-offset: 3px;
}

.skip-link {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 100;
  padding: 9px 13px;
  transform: translateY(-160%);
  border-radius: 3px;
  background: var(--orange-bright);
  color: #160b03;
  font-weight: 850;
}

.skip-link:focus {
  transform: translateY(0);
}

.section-shell {
  width: var(--shell);
  margin-inline: auto;
}

/* Glass without edges (2026-09-18): the bar runs edge to edge and simply
   dissolves into the footage at its lower end, no line, no corner, no shape.
   A mask fades the glass out over its last 30px, and a faint darkening at the
   very top keeps the wordmark readable against a bright sky. */
.site-header {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 30;
  display: grid;
  width: 100%;
  height: 80px;
  padding-inline: max(24px, calc((100% - 1280px) / 2));
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}

/* The bar's own glass panel.
   The blur lives on this pseudo-element and NEVER on .site-header itself:
   backdrop-filter would make the header the containing block of the fixed
   menu sheet on phones and collapse the whole menu into the 64px bar. A
   pseudo-element has no descendants, so nothing can be trapped inside it.
   The bar is narrower than the window, so the panel is stretched to 100vw
   the same way the hairline below it is.
   Opacity alone has to carry it where backdrop-filter is unsupported, hence
   the @supports step down. */
/* The glass runs 40px below the bar and thins out there on an eased curve, under
   the words, never behind them: the menu always sits on full frost, and the frost
   melts into what is below instead of stopping on an edge. No shading is added
   in the fade, it is blur only. */
.site-header::before {
  position: absolute;
  inset: 0 0 -40px;
  z-index: -1;
  content: "";
  background: linear-gradient(180deg, rgba(4, 9, 15, 0.86), rgba(4, 9, 15, 0.7));
  -webkit-mask-image: linear-gradient(180deg, #000 66%, rgba(0, 0, 0, 0.72) 76%, rgba(0, 0, 0, 0.4) 86%, rgba(0, 0, 0, 0.14) 94%, transparent);
  mask-image: linear-gradient(180deg, #000 66%, rgba(0, 0, 0, 0.72) 76%, rgba(0, 0, 0, 0.4) 86%, rgba(0, 0, 0, 0.14) 94%, transparent);
  pointer-events: none;
}

/* With blur available the pane goes nearly clear: what tints it is mostly the
   footage behind, blurred and a touch richer. */
@supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .site-header::before {
    background-color: rgba(4, 9, 15, 0.24);
    background-image: linear-gradient(180deg, rgba(3, 7, 12, 0.14), transparent 66%);
    -webkit-backdrop-filter: blur(16px) saturate(170%);
    backdrop-filter: blur(16px) saturate(170%);
  }

  /* The second step: a lighter blur over the lower band, fading both ways, so
     the footage goes from frosted to clear by degrees instead of one blur
     switching off. */
  .site-header::after {
    position: absolute;
    inset: 0 0 -40px;
    z-index: -1;
    display: block;
    content: "";
    -webkit-mask-image: linear-gradient(180deg, transparent 62%, #000 82%, rgba(0, 0, 0, 0.5) 92%, transparent 100%);
    mask-image: linear-gradient(180deg, transparent 62%, #000 82%, rgba(0, 0, 0, 0.5) 92%, transparent 100%);
    -webkit-backdrop-filter: blur(5px) saturate(140%);
    backdrop-filter: blur(5px) saturate(140%);
    pointer-events: none;
  }
}

/* Over the video the pane is nearly clear (the hero has its own shade up there).
   Once the page itself scrolls under, white headings and bright pictures pass
   behind the menu, so the tint deepens over the first 60vh of scroll. A
   scroll-driven animation: it only runs while that range is being scrolled. */
@supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  @supports (animation-timeline: scroll()) {
    @media (min-width: 981px) {
      .site-header::before {
        animation: glass-tint linear both;
        animation-timeline: scroll(root block);
        animation-range: 0 60vh;
      }
    }
  }
}

@keyframes glass-tint {
  from { background-color: transparent; }
}

/* Refraction (Chromium): the backdrop is bent through a displacement map before
   the blur, so the footage warps as it passes under the pane, like light through
   thick glass. The map is a smooth noise field baked into this data URI. Browsers
   that cannot filter a backdrop through SVG keep the plain blur above. The pane
   is 84px tall, and this is the only per-frame filter on the site; do not reuse
   the technique on anything larger. */
@supports (backdrop-filter: url("#x")) {
  .site-header::before {
    -webkit-backdrop-filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'><feTurbulence type='fractalNoise' baseFrequency='0.006 0.02' numOctaves='2' seed='7' result='n'/><feDisplacementMap in='SourceGraphic' in2='n' scale='18' xChannelSelector='R' yChannelSelector='G'/></filter></svg>#g") blur(10px) saturate(170%);
    backdrop-filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'><feTurbulence type='fractalNoise' baseFrequency='0.006 0.02' numOctaves='2' seed='7' result='n'/><feDisplacementMap in='SourceGraphic' in2='n' scale='18' xChannelSelector='R' yChannelSelector='G'/></filter></svg>#g") blur(10px) saturate(170%);
  }
}

.site-header::after {
  display: none;
}

/* Weak machines: with the bar pinned, everything scrolling under it would be
   re-blurred and re-bent every frame, so there it is a still, tinted pane. */
html.is-lite .site-header::before {
  background: rgba(4, 9, 15, 0.84);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  animation: none;
}

html.is-lite .site-header::after {
  display: none;
}

.wordmark {
  justify-self: start;
  color: #f3f7fa;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6), 0 0 2px rgba(0, 0, 0, 0.35);
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: 0.4em;
  line-height: 1;
  text-transform: uppercase;
}

.site-navigation {
  display: flex;
  align-self: stretch;
  align-items: center;
  gap: 4px;
}

/* Links in the glass bar: the pointer lights a soft pane behind the word, the
   same material as the bar. The old orange line at the bottom of the bar is
   gone: with the bar dissolving into the footage it floated in mid-air. */
.site-navigation a {
  position: relative;
  display: inline-flex;
  height: 42px;
  /* legibility over bright footage comes from the words, not a darker bar */
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6), 0 0 2px rgba(0, 0, 0, 0.35);
  align-items: center;
  padding: 0 16px;
  border-radius: 999px;
  color: #b9c6d0;
  font-size: 0.98rem;
  font-weight: 820;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: color 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
}

.site-navigation a:hover,
.site-navigation a.is-active {
  background-color: rgba(255, 255, 255, 0.09);
  color: white;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.site-navigation a.is-active {
  background-color: rgba(245, 154, 50, 0.14);
  box-shadow: inset 0 0 0 1px rgba(245, 154, 50, 0.22);
}

.menu-toggle {
  display: none;
}

.launcher-hero {
  position: relative;
  min-height: max(800px, 108svh);
  overflow: hidden;
  isolation: isolate;
}

.launcher-backdrop {
  position: absolute;
  inset: 0;
  z-index: -5;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center center;
  translate: 0 var(--hero-parallax);
  will-change: translate, transform;
  animation: backdrop-drift 18s ease-in-out infinite alternate;
}

@keyframes backdrop-drift {
  from { transform: scale(1.015); }
  to { transform: scale(1.045) translate3d(-0.2%, -0.25%, 0); }
}

/* The poster, the video and their shade in one layer that fades out over its
   lower third, so the footage dissolves into the page's sky with no edge. One
   static mask on one layer. */
.hero-media {
  position: absolute;
  inset: 0;
  z-index: -5;
  -webkit-mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 62%, transparent 100%);
}

/* Hero background: the Gold Box loop (owner, 2026-09-17). The poster paints at once; app.js
   loads the video after the page has loaded, never in lite mode, on data saver or with reduced
   motion, and fades it in over the poster. No filter on either layer (speed rules). */
.hero-poster,
.hero-video {
  position: absolute;
  inset: 0;
  z-index: -5;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center center;
}

.hero-video {
  opacity: 0;
  transition: opacity 600ms ease;
}

.hero-video.is-playing {
  opacity: 1;
}

.hero-shade {
  position: absolute;
  inset: 0;
  z-index: -4;
  background:
    /* darker where the copy sits, so it reads over moving footage without a text box */
    radial-gradient(ellipse 44% 46% at 50% 44%, rgba(3, 8, 14, 0.66) 0%, rgba(3, 8, 14, 0.46) 55%, rgba(3, 8, 14, 0.2) 100%),
    linear-gradient(180deg, rgba(3, 7, 11, 0.16) 0%, rgba(3, 7, 11, 0.16) 58%, rgba(5, 13, 22, 0.72) 100%);
}

.screen-filter {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 12;
  pointer-events: none;
  opacity: 0.32;
  background-image:
    linear-gradient(112deg, transparent 45%, rgba(219, 233, 242, 0.07) 48.6%, rgba(3, 7, 11, 0.19) 49.5%, transparent 53%) 8% 16% / 340px 140px no-repeat,
    linear-gradient(74deg, transparent 45%, rgba(219, 233, 242, 0.05) 48.7%, transparent 52%) 76% 62% / 220px 350px no-repeat,
    linear-gradient(123deg, transparent 44%, rgba(4, 8, 12, 0.28) 48.5%, rgba(214, 227, 236, 0.03) 49.6%, transparent 53%) 45% 86% / 480px 130px no-repeat;
  box-shadow: inset 0 0 130px 26px rgba(0, 0, 0, 0.52);
  mix-blend-mode: screen;
  animation: screen-shift 9s steps(2, end) infinite;
}

.screen-filter::before,
.screen-filter::after {
  position: absolute;
  content: "";
  pointer-events: none;
}

.screen-filter::before {
  inset: 0;
  opacity: 0.14;
  background:
    radial-gradient(circle at 13% 22%, white 0 0.5px, transparent 1px),
    radial-gradient(circle at 72% 34%, white 0 0.5px, transparent 1px),
    radial-gradient(circle at 44% 76%, white 0 0.5px, transparent 1px),
    radial-gradient(circle at 89% 64%, white 0 0.5px, transparent 1px);
  background-size: 61px 53px, 79px 67px, 47px 83px, 71px 59px;
}

.screen-filter::after {
  top: -20%;
  bottom: -20%;
  left: 50%;
  width: 1px;
  transform: rotate(13deg);
  background: rgba(214, 229, 239, 0.14);
  box-shadow: 46px 0 rgba(214, 229, 239, 0.045), -219px 0 rgba(214, 229, 239, 0.035);
}

@keyframes screen-shift {
  0%, 100% { transform: translate(0); opacity: 0.3; }
  45% { transform: translate(0.4px, -0.3px); opacity: 0.35; }
  46% { transform: translate(-0.3px, 0.4px); opacity: 0.28; }
}

.lightning-flash {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  opacity: 0;
  background:
    radial-gradient(circle at 50% 13%, rgba(255, 255, 255, 0.95), rgba(178, 213, 255, 0.52) 14%, transparent 42%),
    rgba(153, 196, 242, 0.2);
  mix-blend-mode: screen;
  animation: lightning 10.5s infinite;
}

@keyframes lightning {
  0%, 72%, 73.5%, 75.2%, 100% { opacity: 0; }
  72.25% { opacity: 0.62; }
  72.5% { opacity: 0.08; }
  72.85% { opacity: 0.38; }
  74.4% { opacity: 0.15; }
}

.pumpkin-light-art {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center center;
  translate: 0 var(--hero-parallax);
  pointer-events: none;
  mix-blend-mode: screen;
  will-change: opacity, transform;
  animation: backdrop-drift 18s ease-in-out infinite alternate;
}

/* The bloom is a pre-blurred 960px image (assets/hero-pumpkin-bloom-960.webp).
   It used to be the full 3840x2160 PNG with blur + two drop-shadows animated in
   the keyframes, which re-filtered a screen-sized layer at 60 fps forever. Only
   opacity animates now. */
.pumpkin-light-bloom {
  opacity: 0.18;
  animation:
    backdrop-drift 18s ease-in-out infinite alternate,
    pumpkin-bloom 3.4s ease-in-out infinite;
}

.pumpkin-light-core {
  z-index: 3;
  opacity: 0.24;
  animation:
    backdrop-drift 18s ease-in-out infinite alternate,
    pumpkin-core 2.15s steps(8, end) infinite;
}

@keyframes pumpkin-bloom {
  0%, 100% { opacity: 0.12; }
  36% { opacity: 0.28; }
  58% { opacity: 0.19; }
  76% { opacity: 0.32; }
}

@keyframes pumpkin-core {
  0%, 100% { opacity: 0.18; }
  21% { opacity: 0.34; }
  29% { opacity: 0.23; }
  63% { opacity: 0.4; }
  71% { opacity: 0.26; }
}

.particle-layer {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  pointer-events: none;
}

.ember {
  position: absolute;
  bottom: var(--y);
  left: var(--x);
  width: var(--size);
  height: var(--height);
  border-radius: 50%;
  background: var(--ember-color);
  box-shadow: 0 0 var(--glow) var(--ember-color), 0 0 var(--glow-wide) rgba(255, 119, 31, 0.22);
  opacity: 0;
  mix-blend-mode: screen;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
  animation: ember-rise var(--duration) linear var(--delay) infinite;
}

.ember-far {
  mix-blend-mode: lighten;
}

.ember-near {
  box-shadow: 0 0 var(--glow) var(--ember-color), 0 0 var(--glow-wide) rgba(255, 106, 22, 0.3);
}

.ember-streak {
  border-radius: 60% 60% 45% 45%;
}

.ember-streak::after {
  position: absolute;
  top: 72%;
  left: 50%;
  width: 52%;
  height: 230%;
  content: "";
  transform: translateX(-50%);
  border-radius: 999px;
  background: linear-gradient(180deg, var(--ember-color), transparent 82%);
  opacity: 0.28;
}

@keyframes ember-rise {
  0% { transform: translate3d(0, 24px, 0) rotate(var(--rotation)) scale(0.42); opacity: 0; }
  9% { opacity: var(--opacity); }
  48% { transform: translate3d(var(--drift-mid), var(--rise-mid), 0) rotate(var(--rotation-mid)) scale(0.92); opacity: var(--mid-opacity); }
  77% { opacity: var(--opacity); }
  100% { transform: translate3d(var(--drift), var(--rise-end), 0) rotate(var(--rotation-end)) scale(0.18); opacity: 0; }
}

.bat-layer {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  pointer-events: none;
}

.bat {
  position: absolute;
  display: block;
  width: 42px;
  height: 22px;
  opacity: 0;
  filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.7));
  will-change: transform, opacity;
}

.bat-body {
  position: absolute;
  top: 7px;
  left: 18px;
  z-index: 2;
  width: 7px;
  height: 13px;
  border-radius: 52% 52% 65% 65%;
  background: #020407;
  box-shadow: inset 0 0 3px rgba(100, 141, 176, 0.3);
}

.bat-body::before,
.bat-body::after {
  position: absolute;
  top: -3px;
  width: 4px;
  height: 5px;
  content: "";
  background: #020407;
  clip-path: polygon(0 100%, 50% 0, 100% 100%);
}

.bat-body::before { left: 0; }
.bat-body::after { right: 0; }

.bat-wing {
  position: absolute;
  top: 3px;
  width: 22px;
  height: 17px;
  background: #020407;
  will-change: transform;
}

.bat-wing-left {
  left: 0;
  clip-path: polygon(100% 34%, 74% 5%, 65% 34%, 28% 0, 40% 43%, 0 31%, 34% 100%, 68% 68%, 100% 82%);
  transform-origin: right center;
  animation: bat-flap-left 0.48s ease-in-out infinite alternate;
}

.bat-wing-right {
  right: 0;
  clip-path: polygon(0 34%, 26% 5%, 35% 34%, 72% 0, 60% 43%, 100% 31%, 66% 100%, 32% 68%, 0 82%);
  transform-origin: left center;
  animation: bat-flap-right 0.48s ease-in-out infinite alternate;
}

@keyframes bat-flap-left {
  from { transform: rotate(-9deg) scaleY(1); }
  to { transform: rotate(16deg) scaleY(0.42); }
}

@keyframes bat-flap-right {
  from { transform: rotate(9deg) scaleY(1); }
  to { transform: rotate(-16deg) scaleY(0.42); }
}

.bat-one {
  top: 18%;
  left: -6%;
  animation: bat-flight-one 16s ease-in-out 1s infinite;
}

.bat-two {
  top: 30%;
  left: -8%;
  scale: 0.78;
  animation: bat-flight-two 20s ease-in-out 7s infinite;
}

.bat-three {
  top: 13%;
  right: -7%;
  scale: 0.86;
  animation: bat-flight-three 23s ease-in-out 11s infinite;
}

.bat-four {
  top: 24%;
  left: -7%;
  scale: 0.66;
  animation: bat-flight-two 26s ease-in-out 15s infinite;
}

@keyframes bat-flight-one {
  0% { transform: translate3d(0, 24px, 0) rotate(-7deg) scale(0.8); opacity: 0; }
  10%, 84% { opacity: 0.72; }
  38% { transform: translate3d(44vw, -16px, 0) rotate(5deg) scale(0.92); }
  68% { transform: translate3d(82vw, 25px, 0) rotate(-4deg) scale(1); }
  100% { transform: translate3d(112vw, -18px, 0) rotate(6deg) scale(0.84); opacity: 0; }
}

@keyframes bat-flight-two {
  0% { transform: translate3d(0, -8px, 0) rotate(4deg) scale(0.76); opacity: 0; }
  12%, 80% { opacity: 0.5; }
  48% { transform: translate3d(60vw, 31px, 0) rotate(-7deg) scale(0.92); }
  100% { transform: translate3d(116vw, -38px, 0) rotate(4deg) scale(0.72); opacity: 0; }
}

@keyframes bat-flight-three {
  0% { transform: translate3d(0, 15px, 0) rotate(-3deg) scaleX(-1) scale(0.74); opacity: 0; }
  12%, 82% { opacity: 0.56; }
  50% { transform: translate3d(-58vw, 42px, 0) rotate(8deg) scaleX(-1) scale(0.88); }
  100% { transform: translate3d(-112vw, -18px, 0) rotate(-5deg) scaleX(-1) scale(0.78); opacity: 0; }
}

.hero-copy {
  position: absolute;
  top: 20%;
  left: 50%;
  z-index: 7;
  width: min(1080px, calc(100% - 48px));
  transform: translateX(-50%);
  text-align: center;
}

.section-label {
  margin: 0 0 13px;
  color: var(--orange-bright);
  font-size: 0.72rem;
  font-weight: 820;
  letter-spacing: 0.3em;
  line-height: 1.3;
  text-transform: uppercase;
}

.hero-copy h1 {
  margin: 0;
  color: #ffffff;
  font-family: "Quadrat Grotesk", "Archivo Black", "Prime Display", "Prime Intl", Impact, sans-serif;
  font-size: clamp(5.23rem, 7.25vw, 7.74rem);
  font-weight: 400;
  letter-spacing: -0.018em;
  line-height: 0.94;
  white-space: nowrap;
  text-transform: lowercase;
  text-shadow: none;
}

.hero-intro {
  width: fit-content;
  max-width: min(860px, calc(100% - 24px));
  margin: 72px auto 0;
  padding: 0;
  color: #f2ede4;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: clamp(0.95rem, 1.17vw, 1.15rem);
  font-weight: 600;
  letter-spacing: 0.012em;
  line-height: 1.5;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.85), 0 4px 14px rgba(0, 0, 0, 0.9);
}

.hero-intro span {
  display: block;
}

.hero-intro strong {
  color: #ffb23f;
  font-weight: inherit;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.85), 0 4px 14px rgba(0, 0, 0, 0.9), 0 0 16px rgba(244, 116, 28, 0.35);
}

/* The two names are the reason most visitors arrive, so they sit in the hero
   rather than in a section nobody scrolls to (owner, 2026-09-18). */
.hero-by {
  margin: 12px auto 0;
  color: #cbd6df;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  line-height: 1.4;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.85), 0 4px 14px rgba(0, 0, 0, 0.9);
}

.hero-by b {
  color: #ffffff;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.hero-facts {
  margin: 14px auto 0;
  text-wrap: balance;
  color: #ffb23f;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  line-height: 1.4;
  text-transform: uppercase;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.85), 0 4px 14px rgba(0, 0, 0, 0.9);
}

.hero-countdown {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin: 22px auto 0;
}

.hero-countdown[hidden] {
  display: none;
}

.hero-countdown > div {
  min-width: 76px;
  padding: 10px 8px 8px;
  border: 1px solid rgba(243, 128, 26, 0.42);
  border-radius: 10px;
  background: rgba(5, 9, 14, 0.62);
}

.hero-countdown b {
  display: block;
  color: #ffffff;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 1.9rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.hero-countdown span {
  display: block;
  margin-top: 6px;
  color: #b8c2cb;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* ---- The original site's green button (owner, 2026-09-18) ------------------
   The 2014 tankionline.com FIGHT! button, from that site's own sprite (our
   assets/nav-sprite.png, where it reads ИГРАТЬ). Its word was drawn into the
   picture, so the art is cut into the real left and right ends plus two clean
   36px pieces of the textured middle (assets/fight-button-v1.webp and the hover
   state, 112 x 86: ends 20px, middle 72px, tiled with "round"). The label is text
   on top, so it reads in every language. Hover fades the original's lighter
   state in, as the site did; only opacity and transform move. Only the main
   action wears it: every other button stays orange. */
.fight-button {
  --fb-h: 60px;
  --fb-cap: calc(var(--fb-h) * 20 / 86);
  position: relative;
  display: inline-grid;
  place-items: center;
  min-height: var(--fb-h);
  padding: 6px calc(var(--fb-cap) + 14px) 7px;
  isolation: isolate;
  border: 0;
  background: none;
  color: #e9ff83;
  cursor: pointer;
  font-family: "Tanki Quadrat", "Prime Intl", Arial, sans-serif;
  font-size: 20px;
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 1.1;
  text-align: center;
  text-transform: uppercase;
  text-wrap: balance;
  text-shadow: 0 0 7px rgba(214, 255, 110, 0.5), 0 1px 1px rgba(30, 70, 0, 0.45);
  transition: transform 90ms ease;
}

.fight-button::before,
.fight-button::after {
  position: absolute;
  inset: 0;
  z-index: -1;
  content: "";
  border-style: solid;
  border-width: 0 var(--fb-cap);
  border-image: url("assets/fight-button-v1.webp") 0 20 fill / 0 var(--fb-cap) / 0 round stretch;
  pointer-events: none;
}

.fight-button::after {
  border-image-source: url("assets/fight-button-hover-v1.webp");
  opacity: 0;
  transition: opacity 160ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .fight-button:hover::after {
    opacity: 1;
  }
}

.fight-button:active {
  transform: translateY(1px);
}

.fight-button:focus-visible {
  outline-color: #e9ff83;
}

.fight-button:disabled {
  cursor: default;
  opacity: 0.6;
  transform: none;
}

/* ---- Discord's button (owner, 2026-09-18) ------------------------------------
   Everything that opens our Discord wears Discord's blurple and white logo, at
   rest and on hover (a deeper blurple, never the site's orange), so it reads as
   Discord before the words are read. */
.discord-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 56px;
  padding: 0 26px;
  border: 0;
  border-radius: 12px;
  background-color: var(--discord);
  box-shadow: 0 10px 24px rgba(88, 101, 242, 0.3), inset 0 1px rgba(255, 255, 255, 0.16);
  color: #ffffff;
  cursor: pointer;
  font-family: inherit;
  font-size: 1.05rem;
  font-weight: 800;
  line-height: 1.2;
  text-decoration: none;
  transition: background-color 150ms ease, box-shadow 150ms ease, transform 110ms ease;
}

.discord-button::before {
  flex: none;
  width: 24px;
  height: 24px;
  content: "";
  background-color: currentColor;
  -webkit-mask: url("assets/nav-discord.svg") no-repeat center / contain;
  mask: url("assets/nav-discord.svg") no-repeat center / contain;
}

.discord-button:hover {
  background-color: var(--discord-deep);
  box-shadow: 0 12px 28px rgba(88, 101, 242, 0.4), inset 0 1px rgba(255, 255, 255, 0.12);
  color: #ffffff;
  transform: translateY(-1px);
}

.discord-button:active {
  background-color: var(--discord-press);
  transform: none;
}

.discord-button:focus-visible {
  outline-color: var(--discord-light);
}

.discord-button--small {
  min-height: 46px;
  padding: 0 20px;
  font-size: 0.98rem;
}

.discord-button--block {
  display: flex;
  width: 100%;
}

/* Two lines inside: the action, and the date under it. */
.discord-button__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.discord-button__copy small {
  color: rgba(255, 255, 255, 0.82);
  font-size: 0.8rem;
  font-weight: 600;
}

.article-cta .discord-button {
  min-height: 60px;
}

/* The homepage hero: centred under the countdown. */
.fight-button--hero {
  --fb-h: 64px;
  display: grid;
  width: fit-content;
  max-width: 100%;
  margin: 28px auto 0;
  font-size: 23px;
}

/* A form's submit: the full width of its card. */
.fight-button--block {
  --fb-h: 58px;
  display: grid;
  width: 100%;
  margin-top: 14px;
}

@keyframes pumpkin-melt {
  from { background-position: 12% 8%, 86% 92%, 50% 100%, center; }
  to { background-position: 30% 22%, 67% 71%, 58% 82%, center; }
}

/* A tile with nowhere to go is not a link and must not pretend to be one:
   no pointer, no lift, no zoom. */
.card-badge {
  position: absolute;
  top: 16px;
  left: 16px;
  padding: 6px 12px;
  border-radius: 5px;
  background: var(--orange);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.32);
  color: #211004;
  font-size: 0.78rem;
  font-weight: 900;
  letter-spacing: 0.12em;
  line-height: 1.4;
  text-transform: uppercase;
}

/* The section runs the full width so the light band behind it reaches both edges;
   its heading and tiles sit on the page grid like every other section. */
.news-section {
  position: relative;
  z-index: 2;
  isolation: isolate;
  width: 100%;
  margin-inline: 0;
  padding-block: 0 clamp(48px, 6vw, 72px);
  overflow-x: clip;
}

.section-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 10px 30px;
  margin-bottom: 30px;
}

.section-heading h2,
.game-copy h2,
.ladder-copy h2,
.return-copy h2,
.grow-col h2 {
  margin: 0;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: var(--display-size);
  font-weight: 900;
  letter-spacing: var(--display-tracking);
  word-spacing: var(--display-words);
  line-height: 0.96;
  text-transform: uppercase;
  text-wrap: balance;
}

.news-section .section-heading h2,
.return-copy h2,
.grow-col h2 {
  font-size: var(--title-size);
  line-height: 1.02;
}

.news-controls {
  display: flex;
  gap: 7px;
}

.news-controls button {
  display: grid;
  width: 50px;
  height: 50px;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: #08101a;
  color: #a8b5bf;
  font-size: 1.9rem;
  line-height: 1;
  cursor: pointer;
  transition: transform 150ms ease, border-color 150ms ease, background 150ms ease, color 150ms ease;
}

.news-controls button:hover {
  transform: scale(1.08);
  border-color: rgba(245, 154, 50, 0.68);
  background: #1e1510;
  color: var(--orange-bright);
}

/* The arrows only steer the swipe strip on phones. On wider screens the tiles
   are a grid that never scrolls, so the buttons would be dead controls. */
@media (min-width: 981px) {
  .news-controls {
    display: none;
  }
}

.news-grid {
  display: grid;
  width: var(--shell);
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
  margin-inline: auto;
}

/* All four tiles are visible at every size, but four across only works once
   there is room for them. Between the tablet layout and a wide desktop they go
   two by two, which keeps the pictures big enough to read instead of squeezing
   four 210px cards into a laptop screen. */
@media (min-width: 981px) and (max-width: 1180px) {
  .news-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Four across leaves less room for a headline, so it wraps rather than being
   cut off with an ellipsis. */
@media (min-width: 1181px) {
  .news-grid .news-item-meta strong {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    white-space: normal;
  }
}

/* The heading and the tiles share the page grid, so their left edges line up
   with every section above and below. */
.news-section .section-heading {
  width: var(--shell);
  margin-inline: auto;
}

/* The strip's tiles are narrow, so the date sits under the headline, as on phones. */
.news-grid .news-item-meta {
  flex-direction: column;
  gap: 6px;
}

.game-section {
  display: grid;
  /* The copy column is wide enough for "It plays like" on one line at full size. */
  grid-template-columns: minmax(0, 1.1fr) minmax(330px, 0.9fr);
  gap: clamp(40px, 6vw, 76px);
  align-items: center;
  padding-block: 80px 130px;
}

/* A real screenshot, framed at its own proportions (880 x 689) so nothing is cut. */
.game-art {
  position: relative;
  overflow: hidden;
  aspect-ratio: 880 / 689;
  border: 1px solid rgba(179, 201, 217, 0.22);
  border-radius: 6px;
  background: #060b11;
  box-shadow:
    0 35px 66px rgba(0, 0, 0, 0.55),
    22px 0 46px rgba(118, 126, 134, 0.08),
    inset 0 1px rgba(255, 255, 255, 0.04);
}

/* A still inner shade, so the picture's edges settle into the dark page. */
.game-art::after {
  position: absolute;
  inset: 0;
  content: "";
  box-shadow: inset 0 0 70px rgba(3, 8, 14, 0.5);
  pointer-events: none;
}

.game-art img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.game-copy > p:not(.section-label) {
  max-width: 560px;
  margin: 22px 0 0;
  color: #c3cfd8;
  font-size: 1.2rem;
  line-height: 1.7;
}

/* The four nostalgia pages used to live only in the footer, where almost nobody
   found them, even though they convert better than the homepage does. */
.game-copy > p.story-lead {
  margin-top: 34px;
  color: #93a6b5;
  font-size: 0.95rem;
  letter-spacing: 0.03em;
}

.story-links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 14px;
}

.story-links a {
  display: inline-flex;
  align-items: center;
  padding: 9px 15px;
  border: 1px solid rgba(184, 207, 224, 0.22);
  border-radius: 999px;
  background: rgba(6, 12, 19, 0.5);
  color: #d7e2ec;
  font-size: 0.95rem;
  font-weight: 700;
  transition: border-color 150ms ease, background 150ms ease, color 150ms ease;
}

.story-links a:hover {
  border-color: rgba(243, 128, 26, 0.75);
  background: rgba(243, 128, 26, 0.1);
  color: #ffffff;
}

/* ---- Homepage: welcome, ladder, old players, friends and creators ---------
   (owner, 2026-09-18) Four blocks with four different rhythms on purpose: a quote
   with no box, a strip of real game art, one strong band with a button, and two
   plain columns. The same card repeated four times is what makes a page look
   generated. */

/* Sections glide in once as they reach the screen. Only opacity and transform
   move. Without JS, or with reduced motion, app.js never adds .can-reveal and
   everything is simply there. */
.can-reveal [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 34px, 0);
  transition:
    opacity 800ms cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 1000ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.can-reveal [data-reveal].is-shown {
  opacity: 1;
  transform: none;
}

/* Welcome: the two of them, then one quote. No card, so it reads as someone
   talking to you and not as a feature box. */
.welcome-section {
  padding-block: clamp(88px, 11vw, 144px) clamp(40px, 6vw, 70px);
  text-align: center;
}

.welcome {
  margin: 0;
}

.welcome-faces {
  display: inline-flex;
  margin-bottom: 30px;
}

.welcome-faces img {
  width: 92px;
  height: 92px;
  border: 3px solid var(--page);
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 0 0 1px var(--line-strong), 0 16px 32px rgba(0, 0, 0, 0.55);
}

.welcome-faces img + img {
  margin-left: -16px;
}

.welcome-quote {
  max-width: 900px;
  margin: 0 auto;
}

.welcome-quote p {
  margin: 0;
  color: var(--text);
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: clamp(1.45rem, 2.6vw, 2.15rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.38;
  text-wrap: balance;
}

/* One sentence per line, so "This time, you play with us." lands on its own. */
.welcome-quote p span {
  display: block;
}

.welcome-sign {
  margin-top: 28px;
  color: var(--orange-bright);
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 0.9rem;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

/* The ladder: the 30 badges from the 2016 client, Recruit to Generalissimo.
   On arrival they light up one after another, which is the climb itself. */
.ladder-section {
  padding-block: clamp(40px, 6vw, 76px) clamp(56px, 8vw, 100px);
  text-align: center;
}

.ladder-copy p {
  max-width: 640px;
  margin: 20px auto 0;
  color: #c3cfd8;
  font-size: 1.2rem;
  line-height: 1.65;
}

.ladder {
  margin-top: clamp(36px, 5vw, 56px);
  padding: clamp(24px, 3vw, 36px) clamp(16px, 3vw, 38px);
  border: 1px solid var(--line);
  border-radius: 10px;
  background:
    radial-gradient(ellipse 45% 130% at 100% 50%, rgba(245, 154, 50, 0.12), transparent 62%),
    linear-gradient(180deg, rgba(16, 28, 41, 0.72), rgba(6, 11, 18, 0.72));
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.45), inset 0 1px rgba(255, 255, 255, 0.04);
}

.ladder-badges {
  display: grid;
  grid-template-columns: repeat(15, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 20px) clamp(4px, 0.8vw, 10px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ladder-badges li {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
}

.ladder-badges img {
  position: relative;
  width: 100%;
  max-width: 60px;
  height: auto;
}

/* Generalissimo, the one everyone is racing for: a still glow, baked into a
   gradient, no filter. */
.ladder-badges li:last-child::before {
  position: absolute;
  inset: -34%;
  content: "";
  background: radial-gradient(circle, rgba(255, 192, 99, 0.34), transparent 64%);
}

.can-reveal .ladder-badges li {
  opacity: 0.12;
  transform: translate3d(0, 10px, 0) scale(0.86);
  transition:
    opacity 400ms ease,
    transform 520ms cubic-bezier(0.2, 0.8, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 20ms + 160ms);
}

.can-reveal .is-shown .ladder-badges li {
  opacity: 1;
  transform: none;
}

.ladder-ends {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 24px;
  color: var(--muted);
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.ladder-ends span:last-child {
  color: var(--orange-bright);
}

.ladder-ends i {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, rgba(190, 210, 226, 0.3), rgba(255, 192, 99, 0.75));
}

/* Old players: one band, one button, to /welcome-back. */
.return-section {
  padding-block: clamp(20px, 3vw, 36px);
}

.return-band {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(24px, 4vw, 56px);
  padding: clamp(30px, 4vw, 50px) clamp(26px, 4.5vw, 58px);
  border: 1px solid rgba(255, 192, 99, 0.28);
  border-radius: 12px;
  background:
    radial-gradient(ellipse 70% 150% at 0% 0%, rgba(245, 154, 50, 0.17), transparent 56%),
    linear-gradient(135deg, #13202f 0%, #0a121c 62%, #0c1119 100%);
  box-shadow: 0 34px 80px rgba(0, 0, 0, 0.5), inset 0 1px rgba(255, 255, 255, 0.05);
}

.return-copy p {
  margin: 12px 0 0;
  color: #c3cfd8;
  font-size: 1.15rem;
  line-height: 1.6;
}

.return-button {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 58px;
  padding: 0 28px;
  border: 1.5px solid var(--orange);
  border-radius: 12px;
  background: linear-gradient(180deg, #232c3a, #0b1017);
  color: var(--orange-bright);
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 1.02rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  box-shadow: 0 0 22px rgba(243, 120, 20, 0.28), 0 12px 26px rgba(0, 0, 0, 0.4);
  transition: transform 180ms ease;
}

.return-button::after {
  content: "\2192";
  transition: transform 180ms ease;
}

.return-button:hover {
  transform: translateY(-2px);
}

.return-button:hover::after {
  transform: translateX(4px);
}

/* Friends and creators: two plain columns split by a hairline. */
.grow-section {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  padding-block: clamp(56px, 7vw, 92px) clamp(76px, 9vw, 124px);
}

.grow-col {
  padding: 4px clamp(24px, 4vw, 58px);
}

.grow-col:first-child {
  padding-left: 0;
}

.grow-col + .grow-col {
  padding-right: 0;
  border-left: 1px solid var(--line);
}

.grow-col p {
  max-width: 470px;
  margin: 14px 0 0;
  color: #c3cfd8;
  font-size: 1.12rem;
  line-height: 1.65;
}

.grow-col .discord-button {
  margin-top: 18px;
}

.text-link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 28px;
  color: var(--orange-bright);
  font-size: 0.95rem;
  font-weight: 820;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.text-link span {
  font-size: 1.25rem;
  transition: transform 160ms ease;
}

.text-link:hover span {
  transform: translateX(5px);
}

/* ---- Destinations (2026-09-18). Every card is a compact row by default: title and
   one line on the left, the marker on the right. On desktop the two cards with art
   (.destination-feature: Ratings, Tournaments) grow into tall tiles, and Forum and
   Discord stay rows, so no card is an empty box. ---- */
.links-section {
  position: relative;
  isolation: isolate;
  padding-block: 26px 130px;
}

.destination-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.destination-card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 4px 24px;
  overflow: hidden;
  padding: 26px 28px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: linear-gradient(145deg, rgba(44, 72, 97, 0.11), transparent 52%), var(--panel);
  box-shadow: inset 0 1px rgba(255, 255, 255, 0.04);
  transition: transform 190ms ease, border-color 190ms ease, box-shadow 190ms ease;
}

.destination-card::before {
  position: absolute;
  inset: 0;
  z-index: 0;
  content: "";
  transform: translateY(102%);
  background: linear-gradient(180deg, transparent 12%, rgba(239, 133, 35, 0.04) 54%, rgba(239, 133, 35, 0.19) 100%);
  transition: transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.destination-card::after {
  position: absolute;
  right: 28px;
  bottom: 0;
  left: 28px;
  height: 3px;
  content: "";
  transform: scaleX(0);
  transform-origin: left;
  background: var(--orange);
  box-shadow: 0 0 14px rgba(245, 154, 50, 0.48);
  transition: transform 300ms ease;
}

.destination-card:hover {
  transform: translateY(-5px);
  border-color: rgba(245, 154, 50, 0.54);
  box-shadow: 0 20px 42px rgba(0, 0, 0, 0.42), inset 0 1px rgba(255, 255, 255, 0.055);
}

.destination-card:hover::before {
  transform: translateY(0);
}

.destination-card:hover::after {
  transform: scaleX(1);
}

.destination-wide {
  grid-column: span 2;
}

/* Discord's card (owner, 2026-09-18): at rest it is the dark card it always was,
   with its faint corner glow. On hover or keyboard focus it turns into Discord:
   the blurple layer fades in, the logo slides in and pushes the title across,
   and the words go white. Only opacity and transform move. No orange sweep or
   bar on this card. */
.destination-card.destination-discord {
  background:
    radial-gradient(circle at 100% 0, rgba(245, 145, 48, 0.12), transparent 14rem),
    linear-gradient(145deg, rgba(44, 72, 97, 0.11), transparent 52%),
    var(--panel);
}

.destination-card.destination-discord::before,
.destination-card.destination-discord:hover::before {
  background: linear-gradient(135deg, #6c78f6 0%, var(--discord) 42%, var(--discord-deep) 100%);
  opacity: 0;
  transform: none;
  transition: opacity 260ms ease;
}

.destination-card.destination-discord::after {
  display: none;
}

.destination-card.destination-discord:is(:hover, :focus-visible) {
  border-color: transparent;
  box-shadow: 0 20px 44px rgba(88, 101, 242, 0.34), inset 0 1px rgba(255, 255, 255, 0.18);
}

.destination-card.destination-discord:is(:hover, :focus-visible)::before {
  opacity: 1;
}

/* The logo waits just left of the title, hidden; on hover the title moves one
   logo-width right and the logo fades into the space it left. */
.destination-discord .destination-text strong {
  position: relative;
  transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.destination-discord .destination-text strong::before {
  position: absolute;
  top: 50%;
  left: -1.24em;
  width: 0.92em;
  height: 0.92em;
  content: "";
  opacity: 0;
  transform: translateY(-50%) scale(0.6);
  background-color: currentColor;
  -webkit-mask: url("assets/nav-discord.svg") no-repeat center / contain;
  mask: url("assets/nav-discord.svg") no-repeat center / contain;
  transition: opacity 260ms ease, transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.destination-card.destination-discord:is(:hover, :focus-visible) .destination-text strong {
  transform: translateX(1.24em);
}

.destination-card.destination-discord:is(:hover, :focus-visible) .destination-text strong::before {
  opacity: 1;
  transform: translateY(-50%) scale(1);
}

.destination-discord .destination-text > span {
  transition: color 260ms ease;
}

.destination-card.destination-discord:is(:hover, :focus-visible) .destination-text > span {
  color: rgba(255, 255, 255, 0.9);
}

.destination-card.destination-discord:is(:hover, :focus-visible) .destination-open {
  color: #ffffff;
}

@media (prefers-reduced-motion: reduce) {
  .destination-discord .destination-text strong,
  .destination-discord .destination-text strong::before {
    transition: none;
  }
}

.destination-text,
.destination-open {
  position: relative;
  z-index: 1;
}

.destination-text {
  display: flex;
  flex-direction: column;
}

.destination-text strong {
  margin: 0 0 8px;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: clamp(1.9rem, 2.5vw, 2.6rem);
  font-weight: 900;
  letter-spacing: var(--display-tracking);
  line-height: 1;
  text-transform: uppercase;
}

.destination-text > span {
  color: #b7c4ce;
  font-size: 1.08rem;
  line-height: 1.45;
}

.destination-open {
  color: rgba(203, 215, 224, 0.55);
  font-size: 0.86rem;
  font-weight: 820;
  letter-spacing: 0.11em;
  line-height: 1.3;
  text-transform: uppercase;
  transition: color 180ms ease, transform 180ms ease;
}

.destination-card:hover .destination-open {
  transform: translateX(4px);
  color: var(--orange-bright);
}

/* The trophy only fits the tall tile. */
.tournament-art {
  display: none;
}

@media (min-width: 981px) {
  .destination-feature {
    display: flex;
    min-height: 250px;
    flex-direction: column;
    justify-content: flex-end;
  }

  .destination-feature .destination-text > span {
    max-width: 340px;
    padding-right: 64px;
  }

  .destination-feature .destination-open {
    position: absolute;
    right: 28px;
    bottom: 24px;
  }

  .tournament-art {
    position: absolute;
    top: 18px;
    right: 18px;
    z-index: 1;
    display: block;
    width: 96px;
    height: 96px;
    object-fit: contain;
    filter: drop-shadow(0 10px 14px rgba(0, 0, 0, 0.42));
    transition: transform 220ms ease;
  }

  .destination-card:hover .tournament-art {
    transform: translateY(-3px) scale(1.035);
  }
}

.site-footer {
  margin-top: -140px;
  padding: 204px 0 28px;
  border-top: 0;
  background:
    radial-gradient(circle at 17% 24%, rgba(232, 119, 33, 0.055), transparent 25rem),
    radial-gradient(circle at 82% 30%, rgba(78, 139, 186, 0.07), transparent 28rem),
    linear-gradient(180deg, transparent 0, rgba(3, 9, 15, 0.22) 24%, rgba(3, 8, 14, 0.7) 58%, rgba(3, 8, 14, 0.94) 100%);
  /* The glows would start with a hard edge where the footer begins, under the last
     section; this fades them in. The footer's own content starts below 140px. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 140px);
  mask-image: linear-gradient(180deg, transparent 0, #000 140px);
}

/* Brand on one side, the channels on the other. The page links that used to
   sit here were removed on the owner's call: every one of them is already a
   button on the home page, and repeating them made the footer twice as tall
   as the pages it sits under. */
.footer-main {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 40px;
  padding-bottom: 20px;
}

.footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}

.footer-brand img {
  width: 64px;
  height: 64px;
  object-fit: contain;
}

.footer-brand span {
  display: flex;
  flex-direction: column;
  gap: 5px;
  line-height: 1;
}

.footer-brand b {
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 1.9rem;
  font-weight: 900;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}

.footer-brand small {
  color: var(--muted);
  font-size: 0.92rem;
}

.social-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 22px;
}

.social-links span {
  position: relative;
  display: inline-flex;
  overflow: hidden;
  padding: 4px 0;
  color: #a6b4be;
  font-size: 0.95rem;
  font-weight: 700;
}

/* Each channel is its own logo in a round button: quiet at rest, its brand's
   colour on hover (Discord blurple, TikTok's black with its cyan and pink,
   Facebook blue, Kick green), so it is recognised before it is read. */
.social-links a {
  display: inline-grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.04);
  color: #9fb0bc;
  transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
}

.social-links a::before {
  width: 19px;
  height: 19px;
  content: "";
  background-color: currentColor;
  -webkit-mask: var(--social-logo) no-repeat center / contain;
  mask: var(--social-logo) no-repeat center / contain;
}

.social-links a:hover {
  border-color: transparent;
  color: #ffffff;
  transform: translateY(-2px);
}

.social-links a.social-discord { --social-logo: url("assets/nav-discord.svg"); }
.social-links a.social-tiktok { --social-logo: url("assets/social-tiktok.svg"); }
.social-links a.social-facebook { --social-logo: url("assets/social-facebook.svg"); }
.social-links a.social-kick { --social-logo: url("assets/social-kick.svg"); }
.social-links a.social-youtube { --social-logo: url("assets/social-youtube.svg"); }
.social-links a.social-kick::before { width: 16px; height: 16px; }

.social-links a.social-discord:hover {
  background-color: var(--discord);
  box-shadow: 0 8px 20px rgba(88, 101, 242, 0.4);
}

.social-links a.social-tiktok:hover {
  background-color: #000000;
  box-shadow: -2px 0 0 #25f4ee, 2px 0 0 #fe2c55, 0 8px 20px rgba(0, 0, 0, 0.5);
}

.social-links a.social-facebook:hover {
  background-color: #0866ff;
  box-shadow: 0 8px 20px rgba(8, 102, 255, 0.4);
}

.social-links a.social-youtube:hover {
  background-color: #ff0000;
  box-shadow: 0 8px 20px rgba(255, 0, 0, 0.35);
}

.social-links a.social-kick:hover {
  background-color: #53fc18;
  box-shadow: 0 8px 20px rgba(83, 252, 24, 0.3);
  color: #0b0e0f;
}

.social-links span {
  color: rgba(161, 178, 190, 0.38);
  cursor: not-allowed;
}

.footer-bottom {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  color: rgba(163, 181, 194, 0.45);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.085em;
  text-transform: uppercase;
}

@media (max-width: 980px) {
  :root {
    --gutter: 20px;
    --shell: min(100% - 40px, 900px);
  }

  html {
    scroll-padding-top: 76px;
  }

  /* Sticky, solid header with a full-screen menu sheet */
  .site-header {
    position: sticky;
    top: 0;
    z-index: 40;
    width: 100%;
    height: 64px;
    padding-inline: var(--gutter);
    grid-template-columns: 1fr auto auto;
    column-gap: 10px;
    border-bottom: 1px solid rgba(196, 215, 231, 0.14);
    background: transparent;
  }

  .site-header::before {
    inset: 0;
    background: rgba(4, 9, 15, 0.94);
    -webkit-mask-image: none;
    mask-image: none;
  }

  @supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
    .site-header::before {
      background: rgba(5, 11, 18, 0.5);
    }
  }

  .site-header::after {
    display: none;
  }

  .wordmark {
    font-size: 0.82rem;
    letter-spacing: 0.3em;
  }

  .menu-toggle {
    display: inline-flex;
    min-width: 88px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(243, 128, 26, 0.75);
    border-radius: 8px;
    background: rgba(7, 13, 20, 0.9);
    color: var(--orange-bright);
    cursor: pointer;
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 820;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .site-navigation {
    position: fixed;
    z-index: 39;
    display: none;
    inset: 64px 0 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 10px var(--gutter) calc(24px + env(safe-area-inset-bottom));
    overflow-y: auto;
    background: rgba(3, 8, 14, 0.97);
  }

  .site-navigation.is-open {
    display: flex;
  }

  .site-navigation a {
    display: flex;
    height: auto;
    min-height: 60px;
    align-items: center;
    padding: 0 6px;
    border-bottom: 1px solid rgba(180, 208, 229, 0.12);
    border-radius: 0;
    background: none;
    box-shadow: none;
    font-size: 1.15rem;
    letter-spacing: 0.06em;
  }

  .site-navigation a.nav-discord {
    color: var(--discord-light);
  }

  .launcher-hero {
    min-height: max(640px, calc(100svh - 64px));
  }

  .hero-copy h1 {
    white-space: normal;
    text-wrap: balance;
  }

  .news-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .game-section {
    grid-template-columns: 1fr;
  }

  .ladder-badges {
    grid-template-columns: repeat(10, minmax(0, 1fr));
  }

  .return-band {
    flex-direction: column;
    align-items: flex-start;
  }

  .game-copy {
    max-width: 650px;
  }

  /* The screenshot is 880px wide: past this it only gets softer. */
  .game-art {
    max-width: 640px;
  }

  .destination-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .destination-text strong {
    font-size: clamp(1.25rem, 3.2vw, 1.75rem);
  }

  /* Rows at this size, so the card that is not open yet reads as off at a glance. */
  .destination-card.is-disabled {
    filter: grayscale(1) brightness(0.72);
  }

  .footer-main {
    gap: 18px 32px;
  }
}

@media (max-width: 700px) {
  :root {
    --gutter: max(18px, env(safe-area-inset-left), env(safe-area-inset-right));
    --shell: calc(100% - 2 * var(--gutter));
    --display-size: clamp(2rem, 8.5vw, 2.6rem);
  }

  h1, h2, h3, p {
    overflow-wrap: anywhere;
  }

  /* ---- Hero: laid out in flow, centred, Play inside the first screen ---- */
  .launcher-hero {
    display: flex;
    min-height: calc(100svh - 64px);
    flex-direction: column;
    justify-content: center;
    padding: 28px var(--gutter) 150px;
  }

  .launcher-backdrop,
  .pumpkin-light-art {
    object-position: 58% center;
  }

  .hero-shade {
    background:
      linear-gradient(180deg, rgba(2, 6, 10, 0.7) 0%, rgba(2, 6, 10, 0.42) 22%, rgba(2, 6, 10, 0.5) 50%, rgba(4, 11, 18, 0.62) 78%, rgba(5, 13, 22, 0.74) 100%);
  }

  .hero-countdown > div {
    min-width: 66px;
  }

  .hero-countdown b {
    font-size: 1.6rem;
  }

  .hero-copy {
    position: relative;
    top: auto;
    left: auto;
    width: 100%;
    max-width: 520px;
    margin: 0 auto;
    transform: none;
  }

  .hero-copy h1 {
    font-size: clamp(3.3rem, 16.5vw, 4.6rem);
    letter-spacing: -0.01em;
    line-height: 0.9;
  }

  .hero-intro {
    max-width: 34ch;
    margin: 22px auto 0;
    color: #d8dfe6;
    font-size: 0.92rem;
    line-height: 1.5;
  }

  .hero-intro span {
    display: inline;
  }

  .hero-intro span::after {
    content: " ";
  }

  .hero-intro span:last-child {
    display: block;
    margin-top: 10px;
    color: #ffffff;
    font-size: 1rem;
  }

  .fight-button--hero {
    --fb-h: 56px;
    width: min(360px, 100%);
    margin-top: 24px;
    font-size: 16px;
  }

  .fight-button--block {
    --fb-h: 54px;
    font-size: 16px;
  }

  .bat-three,
  .bat-four,
  .pumpkin-light-bloom {
    display: none;
  }

  /* ---- News: swipe strip with a peek of the next tile ---- */
  .news-section {
    padding-block: 0 48px;
  }

  .news-section .section-heading {
    margin-bottom: 18px;
  }

  .news-controls {
    display: none;
  }

  .news-grid {
    display: grid;
    width: 100%;
    grid-auto-flow: column;
    grid-auto-columns: min(78vw, 320px);
    grid-template-columns: none;
    gap: 14px;
    margin: 0;
    padding: 0 var(--gutter) 8px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-padding-inline: var(--gutter);
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }

  .news-grid::-webkit-scrollbar {
    display: none;
  }

  .news-item {
    scroll-snap-align: start;
  }

  .news-item-meta strong {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    font-size: 1.02rem;
    line-height: 1.25;
    white-space: normal;
  }

  .welcome-section {
    padding-block: 64px 28px;
  }

  .welcome-faces img {
    width: 68px;
    height: 68px;
  }

  .ladder-section {
    padding-block: 46px;
  }

  .ladder-copy p,
  .return-copy p,
  .grow-col p {
    font-size: 1.02rem;
  }

  .ladder {
    padding: 20px 14px;
  }

  .ladder-badges {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 14px 6px;
  }

  .ladder-ends {
    font-size: 0.7rem;
    letter-spacing: 0.12em;
  }

  .return-band {
    padding: 26px 20px;
  }

  .return-button {
    width: 100%;
  }

  .grow-section {
    grid-template-columns: 1fr;
    padding-block: 44px 64px;
  }

  .grow-col,
  .grow-col:first-child,
  .grow-col + .grow-col {
    padding: 0;
  }

  .grow-col + .grow-col {
    margin-top: 30px;
    padding-top: 30px;
    border-top: 1px solid var(--line);
    border-left: 0;
  }

  .hero-by {
    font-size: 0.85rem;
  }

  /* Two deliberate lines: what it is, then when. Never a lone "CEST". */
  .hero-facts-sep {
    display: none;
  }

  .hero-facts-date {
    display: block;
    margin-top: 3px;
  }

  /* ---- The game, rebuilt ---- */
  .game-section {
    gap: 26px;
    padding-block: 40px 56px;
  }

  .game-copy p {
    font-size: 1rem;
    line-height: 1.6;
  }

  /* ---- Destinations: one column of rows ---- */
  .links-section {
    padding-bottom: 64px;
  }

  .destination-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
  }

  .destination-wide {
    grid-column: auto;
  }

  .destination-card {
    gap: 2px 14px;
    padding: 16px 18px;
  }

  .destination-text strong {
    margin-bottom: 3px;
    font-size: 1.2rem;
  }

  .destination-text > span {
    font-size: 0.86rem;
    line-height: 1.4;
  }

  .destination-open {
    font-size: 0.74rem;
  }

  /* ---- Footer ---- */
  .site-footer {
    padding-top: 170px;
  }

  .footer-main {
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
  }

  /* Every channel stays a 44px tap target. */
  .social-links {
    gap: 12px;
  }

  .social-links a {
    width: 46px;
    height: 46px;
  }

  .social-links span {
    display: none;
  }

  .footer-bottom {
    flex-direction: column;
    gap: 5px;
  }
}

/* Lite mode. app.js adds .is-lite to <html> on machines that report 4 cores
   or 4 GB or less, or a data-saver setting. They keep the picture, the pumpkins
   and the copy; they lose the drifting layers, the embers and the bats. */
html.is-lite .particle-layer,
html.is-lite .bat-layer,
html.is-lite .lightning-flash {
  display: none;
}

html.is-lite .launcher-backdrop,
html.is-lite .pumpkin-light-art {
  animation: none;
}

/* The smallest phones: the facts line tightens so every language keeps it to two
   lines (Armenian ran to four at 320px). */
@media (max-width: 380px) {
  .hero-facts {
    font-size: 0.74rem;
    letter-spacing: 0.1em;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .bat-layer,
  .particle-layer,
  .lightning-flash {
    display: none;
  }
}

/* ---- Waitlist form (lives inside the Play modal) ---------------------- */



.notify-form .field {
  margin-bottom: 14px;
}

.notify-form label {
  display: block;
  margin-bottom: 6px;
  color: #93a3ae;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.notify-form input {
  width: 100%;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: rgba(4, 9, 15, 0.8);
  color: var(--text);
  font-family: inherit;
  font-size: 1rem;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

.notify-form input:focus {
  border-color: rgba(243, 128, 26, 0.8);
  box-shadow: 0 0 0 3px rgba(243, 120, 20, 0.16);
  outline: none;
}

.notify-form .cf-turnstile {
  margin: 16px 0 6px;
}

.wl-btn {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
  padding: 15px 20px;
  border: 1.5px solid rgba(243, 128, 26, 0.95);
  border-radius: 12px;
  background:
    radial-gradient(ellipse at 50% 120%, rgba(243, 120, 20, 0.22), transparent 60%),
    linear-gradient(180deg, #232c3a 0%, #121923 55%, #0b1017 100%);
  box-shadow: 0 0 16px rgba(243, 120, 20, 0.35), 0 12px 26px rgba(0, 0, 0, 0.5);
  color: #f2891f;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 160ms ease, box-shadow 160ms ease, transform 110ms ease;
}

.wl-btn:hover {
  border-color: #ffb144;
  box-shadow: 0 0 26px rgba(255, 151, 40, 0.55), 0 14px 30px rgba(0, 0, 0, 0.55);
  transform: translateY(-2px);
}

.wl-btn:disabled {
  cursor: default;
  opacity: 0.6;
  transform: none;
}

.wl-btn .btn-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.wl-btn b {
  font-size: 1.12rem;
  font-weight: 900;
  letter-spacing: 0.01em;
}

.wl-btn small {
  color: #93a3ae;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
}

.wl-btn svg {
  width: 22px;
  height: 22px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.wl-message {
  margin-top: 12px;
  font-size: 0.94rem;
  line-height: 1.45;
}

.wl-message.is-ok { color: #6fdc9a; }
.wl-message.is-err { color: #ff8f7a; }

.wl-fine {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 16px 0 0;
  color: #7f8f9b;
  font-size: 0.82rem;
  line-height: 1.4;
}

.wl-fine svg {
  width: 15px;
  height: 15px;
  flex: none;
  margin-top: 2px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linejoin: round;
}

/* ---- The reservation card on /reserve-nickname --------------------------- */
.reserve-card {
  position: relative;
  width: min(520px, 100%);
  padding: 34px 34px 28px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: linear-gradient(180deg, rgba(20, 32, 46, 0.98), rgba(7, 13, 21, 0.98));
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.6);
}

.reserve-card h1 {
  margin: 12px 0 6px;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 2.15rem;
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 1.02;
  text-wrap: balance;
}

/* The line under the title, "Before someone else takes it.": warm red, the one
   urgent colour on the page (owner, 2026-09-18). */
.reserve-sub {
  margin: 0 0 14px;
  color: #ff6b5a;
  font-size: 1.06rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1.3;
}

.reserve-lead {
  margin: 0 0 24px;
  color: #d5dde5;
  font-size: 1.06rem;
  font-weight: 500;
  line-height: 1.6;
}

.reserve-lead strong {
  color: var(--orange-bright);
  font-weight: 800;
}

/* A destination that is not open yet: reads as inactive, greys out on hover. */
.destination-card.is-disabled {
  /* No cursor change (owner call 2026-09-06): the card just does not react. */
  cursor: default;
}

.destination-card.is-disabled:hover {
  border-color: var(--line);
  transform: none;
  filter: grayscale(1) brightness(0.7);
}

.destination-card.is-disabled:hover .destination-open,
.destination-card.is-disabled .destination-open {
  color: #7d8993;
}

/* ---- Touch devices: drop the effects a phone GPU pays for, and hover states ---- */
@media (hover: none) and (pointer: coarse) {
  .lightning-flash {
    display: none;
  }

  /* Same call as every other blurred surface here: a live blur behind a bar
     that sits over a scrolling page costs more on a phone than it is worth.
     The bar keeps its colour, it just stops blurring. */
  .site-header::before {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(4, 9, 15, 0.88);
  }

  .launcher-backdrop,
  .pumpkin-light-art {
    animation: none;
  }

  .pumpkin-light-core {
    filter: none;
    will-change: auto;
  }

  a.news-item:hover .news-item-art,
  .destination-card:hover,
  .wl-btn:hover {
    transform: none;
  }

  .destination-card:hover::before {
    transform: translateY(102%);
  }

  .destination-card.is-disabled,
  .destination-card.is-disabled:hover {
    filter: grayscale(1) brightness(0.72);
  }
}

/* ---- Phone: the sign-up form (must stay after the base form rules) ---- */
@media (max-width: 700px) {
  .notify-form input {
    min-height: 48px;
    font-size: 16px;
  }

  .wl-btn {
    min-height: 58px;
  }
}

@media (max-width: 380px) {
  .cf-turnstile {
    transform: scale(0.9);
    transform-origin: left center;
  }
}

/* The human check never goes below 300px wide, which pushed the reservation card
   past the edge of a 320px phone. Narrower margins, and the check drawn smaller
   (zoom, unlike scale, also shrinks the space it takes). */
@media (max-width: 380px) {
  .reserve-shell {
    width: calc(100% - 24px);
  }

  .reserve-card {
    padding-inline: 16px;
  }

  .reserve-card .cf-turnstile {
    transform: none;
    zoom: 0.86;
  }

  /* the hints inside the boxes, a touch smaller so they are never cut off (the
     typed text keeps 16px, so iOS does not zoom) */
  .reserve-card input::placeholder {
    font-size: 0.88em;
  }
}

/* ---- Ratings card art (2026-09-05): the leaderboard render behind scratched glass.
   The scratches are a transparent texture (assets/scratches.webp, drawn by hand in
   Python: hairlines, long streaks, nicks and dust) laid over the picture with a screen
   blend. The card already clips (overflow: hidden) and its text sits at z-index 1, so
   every layer here stays underneath the words. ---- */
.destination-ratings {
  background: #070d15;
}

.ratings-art {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: 50% 0;
  transform: scale(1.12);
  transform-origin: 50% 0;
  filter: saturate(0.92) contrast(1.06);
  pointer-events: none;
  transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}

.ratings-screen {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    /* the score column fades out before it reaches the Open marker */
    linear-gradient(270deg, rgba(6, 12, 20, 0.92), rgba(6, 12, 20, 0.4) 20%, transparent 36%),
    /* the shade the card text reads against */
    linear-gradient(180deg, rgba(6, 12, 20, 0.08), rgba(6, 12, 20, 0.42) 58%, rgba(6, 12, 20, 0.92) 100%),
    linear-gradient(90deg, rgba(6, 12, 20, 0.7), rgba(6, 12, 20, 0.18) 45%, transparent 70%);
}

.ratings-screen::after {
  position: absolute;
  inset: 0;
  content: "";
  background: url("assets/scratches-600.webp") center / cover no-repeat;
  mix-blend-mode: screen;
  opacity: 0.21;
}

/* On the desktop tile the words sit dead centre so the left of the picture stays
   visible (owner call 2026-09-06), on a pool of shade so the rows under them do not
   fight the letters. The rows on smaller screens keep the shared left-aligned layout. */
@media (min-width: 981px) {
  .destination-ratings {
    align-items: center;
    justify-content: center;
    text-align: center;
  }

  .destination-ratings .ratings-screen::before {
    position: absolute;
    inset: 0;
    content: "";
    background: radial-gradient(ellipse 34% 60% at 50% 52%, rgba(6, 12, 20, 0.84), rgba(6, 12, 20, 0.5) 62%, transparent 100%);
  }

  .destination-ratings .destination-text {
    align-items: center;
  }

  .destination-ratings .destination-text > span {
    /* Two lines at desktop width: the copy is written to break there. */
    max-width: 40ch;
    padding-right: 0;
    text-wrap: balance;
  }
}

@media (hover: hover) and (pointer: fine) {
  .destination-ratings:hover .ratings-art {
    transform: scale(1.18);
  }
}

@media (max-width: 980px) {
  .ratings-art {
    opacity: 0.8;
  }

  .ratings-screen::after {
    opacity: 0.16;
  }
}

/* ---- Waitlist popup stages (2026-09-06): form, confirm-your-email, already on the list ---- */
.wl-stage[hidden],
.wl-btn[hidden],
.wl-note[hidden] {
  /* the buttons set display: flex, which would otherwise beat the hidden attribute */
  display: none !important;
}

.wl-sent-email {
  color: #ffffff;
  font-weight: 800;
  overflow-wrap: anywhere;
}

.wl-steps {
  margin: 0 0 20px;
  padding: 0;
  list-style: none;
}

.wl-steps li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 9px 0;
  border-top: 1px solid var(--line);
  color: #d5dde5;
  font-size: 0.98rem;
  line-height: 1.45;
}

.wl-steps li:last-child {
  border-bottom: 1px solid var(--line);
}

.wl-steps li > span {
  display: inline-flex;
  width: 26px;
  height: 26px;
  flex: none;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(243, 128, 26, 0.75);
  border-radius: 8px;
  color: var(--orange-bright);
  font-size: 0.8rem;
  font-weight: 900;
}

.wl-steps li > div {
  flex: 1;
  min-width: 0;
}

.wl-steps b {
  color: #ffffff;
}

.wl-note {
  margin: 0 0 16px;
  padding: 10px 12px;
  border: 1px solid rgba(255, 176, 50, 0.35);
  border-radius: 10px;
  background: rgba(243, 120, 20, 0.08);
  color: #ffd39a;
  font-size: 0.92rem;
  line-height: 1.45;
}

.wl-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.wl-actions .wl-btn {
  margin-top: 0;
  text-decoration: none;
}

.wl-btn-secondary {
  width: 100%;
  min-height: 50px;
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  background: rgba(4, 9, 15, 0.6);
  color: #e6edf3;
  cursor: pointer;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 700;
  transition: border-color 160ms ease, color 160ms ease;
}

.wl-btn-secondary:hover {
  border-color: rgba(243, 128, 26, 0.7);
  color: var(--orange-bright);
}

.wl-btn-secondary:disabled {
  cursor: default;
  opacity: 0.55;
}

.wl-link {
  padding: 0;
  border: 0;
  background: none;
  color: #9fb0bf;
  cursor: pointer;
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.wl-link:hover {
  color: var(--orange-bright);
}

@media (max-width: 700px) {
  .reserve-card h1 {
    font-size: 1.7rem;
  }

  .reserve-lead {
    margin-bottom: 20px;
    font-size: 1rem;
  }
}

/* ---- Nickname reservation (2026-09-18): the form on /reserve-nickname, and the
   pages the confirmation email leads to (/reserve-nickname/confirmed, /expired). ---- */
.field-hint {
  margin: 7px 0 0;
  color: #7f8f9b;
  font-size: 0.84rem;
  line-height: 1.45;
}

/* The answer while typing: available, taken, an old player's nickname, blocked. */
.field-status {
  margin: 8px 0 0;
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.45;
}

.field-status:empty {
  display: none;
}

.field-status.is-ok { color: #6fdc9a; }
.field-status.is-err { color: #ff8f7a; }
.field-status.is-legacy { color: #ffd39a; }

.field-status a,
.wl-message a {
  color: inherit;
  font-weight: 800;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.field:has(.field-status.is-ok) input {
  border-color: rgba(111, 220, 154, 0.55);
}

.field:has(.field-status.is-err) input {
  border-color: rgba(255, 143, 122, 0.6);
}

.field[hidden],
.wl-invite[hidden],
.notify-form[hidden] {
  display: none;
}

/* An invite link from email 4: the address is already proven, so it is shown
   (masked) instead of asked for. */
.wl-invite {
  margin: -8px 0 18px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(4, 9, 15, 0.55);
  color: #d5dde5;
  font-size: 0.95rem;
  line-height: 1.45;
}

/* The tank from the game's own "change nickname" screen heads the form. On wide
   screens it stands half out of the card's top edge, so the card makes room for it
   while the form is showing. Its glow is in the picture: no filter.
   The picture's "????????" was painted out (assets/nickname-tank-clean-v1.webp,
   rebuilt from the light rays above and below it) and the name tag is text on
   top: it shows what the player types, live, in the game's own name-tag green
   (#6BCE2A, sampled from the original), and turns enemy red when the nickname
   is taken, blocked or wrong, gold when it belongs to a 2024 player. Its size
   follows the picture's width (cqw), so it sits in the same spot at every size. */
.wl-stage-intro > :is(h1, .reserve-sub, .reserve-lead, .reserve-facts) {
  text-align: center;
}

.wl-art {
  position: relative;
  display: block;
  width: 240px;
  margin: -112px auto 0;
  container-type: inline-size;
  pointer-events: none;
  user-select: none;
}

.wl-art img {
  display: block;
  width: 100%;
  height: auto;
}

.wl-art-name {
  position: absolute;
  top: 20.1%;
  left: 41.7%;
  color: #6bce2a;
  font-family: Tahoma, Verdana, "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 13px;
  font-size: 5.5cqw;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  text-shadow: 0 1px 0 rgba(12, 40, 0, 0.75), 0 0 3px rgba(12, 40, 0, 0.45);
  transform: translateY(-50%);
  transition: color 160ms ease;
}

.wl-art-name[data-state="taken"],
.wl-art-name[data-state="blocked"],
.wl-art-name[data-state="invalid"] {
  color: #ff4b3a;
}

.wl-art-name[data-state="legacy"] {
  color: #ffc947;
}

.reserve-card:has(#wl-stage-form:not([hidden]) .wl-art) {
  margin-top: 78px;
}

/* The facts under the deadline: what it costs, what it runs on, how long to go. */
.reserve-facts {
  margin: -10px 0 24px;
  color: #ffb23f;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  line-height: 1.5;
  text-transform: uppercase;
}

.reserve-days[hidden] {
  display: none;
}

/* The fear a new player has at an email form, answered right above the button. */
.reserve-nopass {
  margin: 14px 0 0;
  color: #93a3ae;
  font-size: 0.9rem;
  line-height: 1.45;
  text-align: center;
}

/* The game, for someone who has never played it: a real battle and three reasons,
   beside the form on desktop and under it on phones (the form comes first). */
.reserve-pitch {
  display: grid;
  gap: 28px;
  width: min(560px, 100%);
  margin-top: 48px;
}

/* The gameplay loop has no frame: it is a little wider than its column and
   dissolves into the sky on every side, so it reads as part of the page's
   background rather than a box laid on it. One static mask; the video is the
   homepage's own. */
.reserve-shot {
  display: block;
  width: calc(100% + 80px);
  max-width: none;
  height: auto;
  aspect-ratio: 16 / 9;
  margin-inline: -40px;
  object-fit: cover;
  background: transparent;
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0, #000 22%, #000 78%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 20%, #000 76%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(90deg, transparent 0, #000 22%, #000 78%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 20%, #000 76%, transparent 100%);
  mask-composite: intersect;
}

.reserve-points {
  display: grid;
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.reserve-points li {
  display: grid;
  gap: 4px;
}

.reserve-points strong {
  color: #ffffff;
  font-size: 1.3rem;
  font-weight: 900;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

.reserve-points span {
  color: #c3cfd8;
  font-size: 1.04rem;
  line-height: 1.55;
}

/* Claudiu & OUFA under the reasons: their faces and the homepage's quote, in
   italic, signed. Someone real is behind the form. */
.reserve-voice {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 22px;
  margin: 8px 0 0;
  padding-top: 28px;
  border-top: 1px solid var(--line);
}

.reserve-voice .welcome-faces {
  margin: 4px 0 0;
}

.reserve-voice .welcome-faces img {
  width: 64px;
  height: 64px;
}

.reserve-voice .welcome-faces img + img {
  margin-left: -14px;
}

.reserve-voice blockquote {
  margin: 0;
}

.reserve-voice p {
  margin: 0;
  color: #e6edf3;
  font-size: 1.14rem;
  font-style: italic;
  font-weight: 600;
  line-height: 1.5;
}

.reserve-voice p span {
  display: block;
}

.reserve-voice figcaption {
  margin-top: 12px;
  color: var(--orange-bright);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* A creator page (/raen, tools/creators.py): the creator who sent the visitor, first
   thing on the left: their face, "Raen invited you", their words, their channels. */
.creator-intro {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 22px;
  margin: 0 0 6px;
}

.creator-face {
  display: grid;
  place-items: center;
  width: 92px;
  height: 92px;
  border: 3px solid var(--page);
  border-radius: 50%;
  object-fit: cover;
  background: linear-gradient(145deg, #2b3f52, #111c27);
  box-shadow: 0 0 0 1px var(--line-strong), 0 16px 32px rgba(0, 0, 0, 0.55);
  color: #ffffff;
  font-size: 2.4rem;
  font-weight: 900;
}

.creator-invited {
  margin: 4px 0 10px;
  color: #ffffff;
  font-size: clamp(1.6rem, 2.4vw, 2.1rem);
  font-weight: 900;
  letter-spacing: -0.02em;
  line-height: 1.12;
}

.creator-intro blockquote {
  margin: 0;
}

.creator-intro blockquote p {
  margin: 0;
  color: #e6edf3;
  font-size: 1.1rem;
  font-style: italic;
  font-weight: 600;
  line-height: 1.5;
}

.creator-sign {
  margin: 10px 0 0;
  color: var(--orange-bright);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.creator-links {
  margin-top: 14px;
  gap: 10px;
}

/* The starting bonus for reserving through a creator's link, in the card under the
   deadline, drawn like the game's own welcome panel: the dark green box, the game's
   icons, big numbers. The numbers are the live ones (tools/creators.py). */
.creator-bonus {
  margin: -6px 0 22px;
  padding: 14px 12px 12px;
  border: 1px solid #0a1b0a;
  border-radius: 12px;
  background: radial-gradient(120% 90% at 50% 0, #1f4a1f, #0c220d 70%);
  box-shadow: inset 0 0 0 1px #436044, 0 14px 30px rgba(0, 0, 0, 0.35);
  text-align: center;
}

.creator-bonus h2 {
  margin: 0 0 8px;
  color: #ffffff;
  font-size: 1rem;
  font-weight: 800;
}

.creator-bonus-items {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}

.creator-bonus-items div {
  display: grid;
  justify-items: center;
  min-width: 0;
}

.creator-bonus-items img {
  width: auto;
  max-width: 100%;
  height: 56px;
  object-fit: contain;
}

.creator-bonus-items strong {
  color: #ffffff;
  font-size: clamp(1.2rem, 6vw, 1.7rem);
  white-space: nowrap;
  font-weight: 900;
  line-height: 1.15;
}

.creator-bonus-items span {
  color: #d7e1d1;
  font-size: 0.8rem;
  line-height: 1.3;
}

.creator-bonus p {
  margin: 10px 0 0;
  color: #c9d8c3;
  font-size: 0.84rem;
  line-height: 1.4;
}

/* The old-name hook above the nickname box, for players coming from other servers. */
.creator-oldnick {
  margin: 0 0 14px;
  color: #ffc15e;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.4;
  text-align: left;
}

/* Three facts under the button that answer "will this server last?". */
.creator-trust {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 18px;
  margin: 16px 0 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--line);
  color: #a9b8c3;
  font-size: 0.84rem;
  line-height: 1.3;
  list-style: none;
}

.creator-trust li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.creator-trust b {
  color: #e6edf3;
}

.creator-trust-faces {
  display: inline-flex;
}

.creator-trust-faces img {
  width: 24px;
  height: 24px;
  border: 2px solid var(--panel, #0d1620);
  border-radius: 50%;
  object-fit: cover;
}

.creator-trust-faces img + img {
  margin-left: -8px;
}

a.creator-trust-discord {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: #a9b8c3;
  text-decoration: none;
  transition: color 150ms ease;
}

a.creator-trust-discord::before {
  width: 18px;
  height: 18px;
  content: "";
  background-color: var(--discord-light);
  -webkit-mask: url("assets/nav-discord.svg") no-repeat center / contain;
  mask: url("assets/nav-discord.svg") no-repeat center / contain;
}

a.creator-trust-discord:hover {
  color: var(--discord-light);
}

.creator-trust-date::before {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  content: "";
  background: #ffb23f;
  box-shadow: 0 0 0 4px rgba(255, 178, 63, 0.18);
}

/* On desktop the creator sits above the footage, level with the card's top edge. */
@media (min-width: 981px) {
  .reserve-shell.reserve-shell--creator {
    grid-template-areas: "intro card" "pitch card";
    grid-template-rows: auto 1fr;
  }

  .reserve-shell--creator .creator-intro {
    grid-area: intro;
    margin-top: 78px;
  }

  .reserve-shell--creator .reserve-pitch {
    margin-top: 32px;
  }
}

/* /reserve-nickname: the page around the card. */
.reserve-shell {
  position: relative;
  display: grid;
  width: min(560px, calc(100% - 48px));
  justify-items: center;
  margin: 0 auto;
  padding: 140px 0 90px;
}

/* The confirmation and expired-link pages: the nickname in the brand colour, and
   the clan line as the one call to action that matters. */
.reserve-result .nick {
  color: var(--orange-bright);
  overflow-wrap: anywhere;
}

.reserve-clan {
  margin: 30px 0 0;
  padding: 18px 20px;
  border: 1px solid rgba(255, 192, 99, 0.28);
  border-radius: 12px;
  background:
    radial-gradient(ellipse 70% 150% at 0% 0%, rgba(245, 154, 50, 0.12), transparent 60%),
    rgba(10, 19, 30, 0.7);
  color: #e6edf3;
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.55;
}

.reserve-result .article-cta {
  margin-top: 22px;
}

@media (max-width: 980px) {
  .reserve-shell {
    padding-top: 40px;
  }
}

/* Phones: the video runs to both screen edges, where its fade meets the sky. */
@media (max-width: 700px) {
  .reserve-shot {
    width: calc(100% + 2 * var(--gutter));
    margin-inline: calc(-1 * var(--gutter));
    -webkit-mask-image:
      linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%),
      linear-gradient(180deg, transparent 0, #000 18%, #000 78%, transparent 100%);
    mask-image:
      linear-gradient(90deg, transparent 0, #000 10%, #000 90%, transparent 100%),
      linear-gradient(180deg, transparent 0, #000 18%, #000 78%, transparent 100%);
  }
}

/* Desktop: the pitch on the left, the form on the right. After the base
   .reserve-shell rule above, which it widens. */
@media (min-width: 981px) {
  .reserve-shell {
    grid-template-columns: minmax(0, 1fr) minmax(0, 520px);
    grid-template-areas: "pitch card";
    column-gap: clamp(40px, 5vw, 80px);
    align-items: start;
    width: min(1180px, calc(100% - 48px));
  }

  .reserve-card {
    grid-area: card;
  }

  /* level with the card's top edge (the card sits 78px down to make room for the tank) */
  .reserve-pitch {
    grid-area: pitch;
    margin-top: 78px;
  }
}

/* Wide screens: the whole layout widens, so the footage is bigger while the page
   stays centred (equal space on both sides). */
@media (min-width: 1300px) {
  .reserve-shell {
    width: min(1320px, calc(100% - 96px));
  }

  .reserve-pitch {
    width: 100%;
  }
}

/* Phones: the tank sits inside the card, smaller, so the form starts higher on a
   small screen. */
@media (max-width: 700px) {
  /* Phones: the creator above the form, compact: face beside the words. */
  .creator-intro {
    gap: 14px;
    width: 100%;
    margin-bottom: 22px;
  }

  .creator-face {
    width: 60px;
    height: 60px;
    font-size: 1.6rem;
  }

  .creator-invited {
    margin-top: 2px;
    font-size: 1.35rem;
  }

  .creator-intro blockquote p {
    font-size: 1rem;
  }

  /* the faces above the quote, so the words keep the full width */
  .reserve-voice {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
  }

  .wl-art {
    width: 176px;
    margin: -10px auto 0;
  }

  .reserve-card:has(#wl-stage-form:not([hidden]) .wl-art) {
    margin-top: 0;
  }
}

@media (max-width: 700px) {
  .reserve-shell {
    width: calc(100% - 2 * var(--gutter));
    padding: 24px 0 64px;
  }

  .reserve-card {
    padding: 26px 20px 22px;
  }

  .reserve-result .article-cta > * {
    flex: 1 1 100%;
  }
}

/* ---- Story pages (2026-09-06): /the-game-you-remember, /gold-box, /ranks, /legends ---- */
.article-shell {
  position: relative;
  width: min(760px, calc(100% - 48px));
  margin: 0 auto;
  padding: 150px 0 90px;
}

.article h1 {
  margin: 0 0 26px;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: clamp(2.4rem, 5vw, 4rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 1.02;
  text-wrap: balance;
}

.article h2 {
  margin: 44px 0 14px;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  font-weight: 900;
  letter-spacing: -0.03em;
  line-height: 1.1;
  text-wrap: balance;
}

.article p {
  margin: 0 0 18px;
  color: #d5dde5;
  font-size: 1.12rem;
  line-height: 1.7;
}

.article p.lead {
  color: #ffffff;
  font-size: 1.3rem;
  font-weight: 500;
  line-height: 1.6;
}

.article ul {
  margin: 0 0 18px;
  padding-left: 22px;
  color: #d5dde5;
  font-size: 1.08rem;
  line-height: 1.65;
}

.article li {
  margin-bottom: 8px;
}

.article .faq dl {
  margin: 0;
}

.article .faq dt {
  margin-top: 18px;
  color: #ffffff;
  font-size: 1.08rem;
  font-weight: 800;
}

.article .faq dd {
  margin: 6px 0 0;
  color: #d5dde5;
  font-size: 1.05rem;
  line-height: 1.6;
}

.article-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 44px;
}

.article-cta :is(a, button):not(.fight-button):not(.discord-button) {
  display: inline-flex;
  min-height: 58px;
  align-items: center;
  justify-content: center;
  padding: 0 30px;
  border-radius: 12px;
  font-size: 1.05rem;
  font-weight: 800;
  text-decoration: none;
  transition: filter 150ms ease, transform 110ms ease;
}

.article-cta button:not(.fight-button):not(.discord-button) {
  cursor: pointer;
  font-family: inherit;
}

.article-cta :is(a, button):not(.fight-button):not(.discord-button):hover {
  filter: brightness(1.12);
  transform: translateY(-1px);
}

.article-cta .cta-main {
  border: 1.5px solid #f2891f;
  background: linear-gradient(180deg, #232c3a 0%, #121923 55%, #0b1017 100%);
  color: #f2891f;
  box-shadow: 0 0 18px rgba(243, 120, 20, 0.35);
}

.article-cta .cta-alt {
  border: 1px solid var(--line-strong);
  background: rgba(4, 9, 15, 0.6);
  color: #e6edf3;
  font-weight: 700;
}

/* /welcome-back: three numbered steps, the numbers drawn by CSS so the
   translations only carry the sentences. */
.article ol.steps {
  display: grid;
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.article ol.steps li {
  position: relative;
  margin: 0;
  padding: 18px 20px 18px 66px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(10, 19, 30, 0.7);
  color: #d5dde5;
  font-size: 1.08rem;
  line-height: 1.6;
  counter-increment: step;
}

.article ol.steps li::before {
  position: absolute;
  top: 16px;
  left: 18px;
  display: grid;
  width: 32px;
  height: 32px;
  place-items: center;
  border: 1.5px solid var(--orange);
  border-radius: 50%;
  color: var(--orange-bright);
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: 0.95rem;
  font-weight: 900;
  content: counter(step);
}

.article p.article-help {
  margin-top: 22px;
  color: var(--muted);
  font-size: 1rem;
}

/* Short pages (a thin news archive, a story page read on a tall screen) used to
   end halfway up the window with bare background under the footer. Make the page
   at least a screen tall and let the main content take the slack, so the footer
   always sits on the bottom edge and never floats in the middle of nowhere. */
body.is-article {
  display: flex;
  min-height: 100vh;
  min-height: 100dvh;
  flex-direction: column;
}

body.is-article > main {
  flex: 1 0 auto;
}

/* No overlap on the story pages, so the fade-in is only as tall as the space above
   the footer's content. */
body.is-article .site-footer {
  margin-top: 0;
  padding-top: 40px;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 40px);
  mask-image: linear-gradient(180deg, transparent 0, #000 40px);
}

@media (max-width: 980px) {
  .article-shell {
    padding-top: 44px;
  }
}

@media (max-width: 700px) {
  .article-shell {
    width: var(--shell);
    padding: 30px 0 64px;
  }

  .article p.lead {
    font-size: 1.15rem;
  }

  .article-cta a {
    width: 100%;
  }
}

/* ==========================================================================
   Languages
   The site is one HTML per page per language; /ka/ is built from the English
   files by tools/i18n.py. Everything below is shared by every language.
   ========================================================================== */

/* The fonts above are Latin only, so one extra family carries every other
   script the site speaks, split by unicode-range: Latin keeps rendering in
   Inter and Anton while Georgian and Cyrillic fall through to these faces. The
   ranges keep them from ever competing for a Latin character. A new script is
   one more @font-face here and no change anywhere else. */
@font-face {
  font-family: "Prime Intl";
  src: url("assets/fonts/noto-sans-georgian-v48-georgian-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0589, U+10A0-10FF, U+1C90-1CBF, U+2D00-2D2F;
}

/* Cyrillic is Inter's own cut, the same version as the Latin file at the top of
   this file, so Russian reads as the site's typeface and not a lookalike. */
@font-face {
  font-family: "Prime Intl";
  src: url("assets/fonts/inter-v20-cyrillic-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* Armenian is Noto Sans Armenian (OFL), Google's Armenian cut. Declared after
   Georgian on purpose: both claim U+0589, the Armenian full stop, and where two
   ranges overlap the face declared last wins. */
@font-face {
  font-family: "Prime Intl";
  src: url("assets/fonts/noto-sans-armenian-v47-armenian-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0530-058F, U+FB13-FB17;
}

.lang-switch {
  position: relative;
  justify-self: end;
  /* lang.js fills this box, so its width is reserved here: without it the
     header re-flows the moment the script runs. */
  min-width: 64px;
  min-height: 38px;
}

.lang-current {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 10px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  color: #dbe6ef;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 820;
  letter-spacing: 0.1em;
  transition: border-color 150ms ease, color 150ms ease;
}

.lang-current:hover,
.lang-switch.is-open .lang-current {
  border-color: rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.13);
  color: #ffffff;
}

.flag {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background-position: center;
  background-size: cover;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.32), 0 1px 3px rgba(0, 0, 0, 0.55);
}

.flag-en { background-image: url("assets/flags/en.svg"); }
.flag-ka { background-image: url("assets/flags/ka.svg"); }
.flag-ru { background-image: url("assets/flags/ru.svg"); }
.flag-pt { background-image: url("assets/flags/br.svg"); }
.flag-de { background-image: url("assets/flags/de.svg"); }
.flag-hy { background-image: url("assets/flags/am.svg"); }

.lang-caret {
  width: 0;
  height: 0;
  margin-left: 1px;
  border-top: 5px solid currentColor;
  border-right: 4px solid transparent;
  border-left: 4px solid transparent;
  opacity: 0.75;
  transition: transform 160ms ease;
}

.lang-switch.is-open .lang-caret {
  transform: rotate(180deg);
}

.lang-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  min-width: 128px;
  margin: 0;
  padding: 6px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 18px;
  background: rgba(8, 14, 22, 0.94);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5);
  list-style: none;
}

/* A small pane of the bar's glass: what is behind it shows through, blurred. */
@supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .lang-menu {
    background:
      linear-gradient(180deg, rgba(255, 255, 255, 0.06), transparent 40%),
      rgba(8, 14, 22, 0.58);
    -webkit-backdrop-filter: blur(22px) saturate(170%);
    backdrop-filter: blur(22px) saturate(170%);
  }
}

.lang-menu li + li {
  margin-top: 2px;
}

.lang-menu a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 12px;
  color: #c8d5e0;
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  transition: background 140ms ease, color 140ms ease;
}

.lang-menu a:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #ffffff;
}

.lang-menu a.is-current {
  background: linear-gradient(180deg, #f8a13a, #e0740f);
  color: #14100a;
}

/* "This page is also in your language": an offer, never a redirect. */
.lang-pill {
  position: fixed;
  right: 0;
  bottom: 18px;
  left: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  gap: 12px;
  width: max-content;
  max-width: min(620px, calc(100% - 28px));
  margin-inline: auto;
  padding: 10px 12px;
  border: 1px solid rgba(196, 215, 231, 0.2);
  border-radius: 14px;
  background: rgba(7, 12, 19, 0.96);
  box-shadow: 0 22px 54px rgba(0, 0, 0, 0.62);
  opacity: 0;
  transform: translate(0, 18px);
  transition: opacity 220ms ease, transform 220ms ease;
}

.lang-pill.is-in {
  opacity: 1;
  transform: translate(0, 0);
}

.lang-pill-text {
  color: #dfe8f0;
  font-size: 0.92rem;
  line-height: 1.35;
}

.lang-pill-go {
  flex: none;
  padding: 8px 14px;
  border: 1px solid rgba(243, 128, 26, 0.85);
  border-radius: 9px;
  background: rgba(243, 128, 26, 0.14);
  color: var(--orange-bright);
  font-size: 0.88rem;
  font-weight: 800;
}

.lang-pill-go:hover {
  background: rgba(243, 128, 26, 0.24);
  color: #ffffff;
}

.lang-pill-x {
  flex: none;
  padding: 8px 4px;
  border: 0;
  background: none;
  color: #8ea1b3;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.82rem;
}

.lang-pill-x:hover {
  color: #dfe8f0;
}

/* Georgian is a wider script with no capital letters, and Russian and Armenian
   words run longer than English ones (Armenian capitals are wide too), so the
   tracking that suits English caps is dialled back wherever text is set in
   uppercase. */
[lang="ka"] .site-navigation a,
[lang="ru"] .site-navigation a,
[lang="hy"] .site-navigation a,
[lang="ka"] .notify-form label,
[lang="ru"] .notify-form label,
[lang="hy"] .notify-form label,
[lang="ka"] .destination-open,
[lang="ru"] .destination-open,
[lang="hy"] .destination-open,
[lang="ka"] .footer-bottom,
[lang="ru"] .footer-bottom,
[lang="hy"] .footer-bottom,
[lang="ka"] .menu-toggle,
[lang="ru"] .menu-toggle,
[lang="hy"] .menu-toggle,
[lang="ka"] .section-label,
[lang="hy"] .section-label {
  letter-spacing: 0.03em;
}

[lang="ka"] .site-navigation a,
[lang="ru"] .site-navigation a,
[lang="hy"] .site-navigation a {
  padding: 0 13px;
  font-size: 0.92rem;
}

[lang="ka"] .fight-button,
[lang="hy"] .fight-button {
  font-size: 0.9em;
  font-weight: 700;
  letter-spacing: 0;
}

[lang="ka"] .article h1,
[lang="ka"] .hero-intro,
[lang="ka"] .article p.lead,
[lang="ru"] .article h1,
[lang="ru"] .hero-intro,
[lang="ru"] .article p.lead,
[lang="pt-BR"] .article h1,
[lang="pt-BR"] .hero-intro,
[lang="pt-BR"] .article p.lead,
[lang="de"] .article h1,
[lang="de"] .hero-intro,
[lang="de"] .article p.lead,
[lang="hy"] .article h1,
[lang="hy"] .hero-intro,
[lang="hy"] .article p.lead {
  text-wrap: pretty;
}

/* Armenian words run long (Գեներալիսիմուս, Պատկերացրու), and at the phone size of
   an article title they did not fit a 320-375px screen, so the phone rule that
   lets a heading break anywhere split them mid-word. One step smaller fits them. */
@media (max-width: 480px) {
  [lang="hy"] .article h1 {
    font-size: 2rem;
  }
}

@media (max-width: 340px) {
  [lang="hy"] .article h1 {
    font-size: 1.75rem;
  }
}

@media (max-width: 980px) {
  .lang-switch { order: 1; min-width: 70px; min-height: 44px; }
  .menu-toggle { order: 2; }

  .lang-current {
    height: 44px;
    padding: 0 10px;
  }

  .lang-menu {
    top: calc(100% + 6px);
    min-width: 136px;
  }

  .lang-menu a {
    padding: 12px 10px;
    font-size: 0.88rem;
  }
}

@media (max-width: 700px) {
  .lang-current {
    gap: 6px;
    padding: 0 8px;
    font-size: 0.72rem;
  }

  .lang-pill {
    right: 12px;
    bottom: 12px;
    left: 12px;
    width: auto;
    max-width: none;
    flex-wrap: wrap;
  }

  .lang-pill-text {
    flex: 1 1 100%;
    min-width: 0;
    font-size: 0.88rem;
  }

  .lang-pill-go {
    flex: 1 1 auto;
    text-align: center;
  }

  .lang-pill-x {
    flex: 0 0 auto;
  }
}

@media (max-width: 380px) {
  .lang-switch { min-width: 48px; }
  .lang-current .lang-code { display: none; }
}

/* ==========================================================================
   /news  the full archive
   Cards are drawn by news-page.js from the same news.json the launcher reads,
   so posting once fills the homepage strip and this page in every language.
   ========================================================================== */

.news-page {
  padding-block: 130px 120px;
}

.news-page h1 {
  margin: 0;
  font-family: "Prime Text", "Prime Intl", Arial, sans-serif;
  font-size: clamp(2.4rem, 4vw, 3.6rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 1;
  text-transform: uppercase;
}

.news-page-lead {
  margin: 14px 0 0;
  color: #93a6b5;
  font-size: 1.05rem;
}

.news-archive {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 28px 24px;
  margin-top: 44px;
}

.news-all {
  align-self: center;
  color: var(--orange-bright);
  font-size: 0.86rem;
  font-weight: 820;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

.news-all:hover {
  color: #ffffff;
}

.news-archive-state {
  grid-column: 1 / -1;
  margin: 0;
  padding: 40px 0;
  color: #93a6b5;
  font-size: 1.05rem;
}

.news-item {
  display: block;
  color: inherit;
}

.news-item-art {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  border: 1px solid rgba(184, 207, 224, 0.2);
  border-radius: 10px;
  background: #09101a;
  box-shadow: 0 17px 32px rgba(0, 0, 0, 0.45);
  transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease;
}

.news-item-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

a.news-item:hover .news-item-art {
  transform: translateY(-3px);
  border-color: rgba(245, 154, 50, 0.72);
  box-shadow: 0 22px 38px rgba(0, 0, 0, 0.54), 0 0 22px rgba(245, 132, 35, 0.09);
}

a.news-item.news-item-logo:hover .news-item-art {
  border-color: rgba(88, 101, 242, 0.9);
  box-shadow: 0 22px 38px rgba(0, 0, 0, 0.54), 0 0 22px rgba(88, 101, 242, 0.28);
}

a.news-item:hover .news-item-art img {
  transform: scale(1.04);
}

.news-item-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
}

.news-item-meta strong {
  font-size: 1.02rem;
  font-weight: 800;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}

.news-item-meta time,
.news-item-meta > span {
  flex: none;
  color: #8397a7;
  font-size: 0.84rem;
  font-weight: 700;
  white-space: nowrap;
}

@media (max-width: 980px) {
  .news-page {
    padding-block: 40px 90px;
  }

  .news-archive {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px 18px;
    margin-top: 32px;
  }
}

@media (max-width: 700px) {
  .news-archive {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
  }

  .news-item-meta {
    flex-direction: column;
    gap: 5px;
  }
}

/* ===========================================================================
   TOP-BAR ICONS
   ---------------------------------------------------------------------------
   One sprite carries every nav icon: assets/nav-sprite.png holds a white row
   and, 30px to its right, the same icon in green. White is the resting state,
   green is hover / current page - the same behaviour the forum's bar uses, so
   the two bars stay in step.

   Every nav link is built the same way, on every page and in every language:

       <a href="..." data-umami-event="nav_click" data-umami-event-target="KEY">
         <i class="nav-ico nav-ico--KEY" aria-hidden="true"></i>
         <span data-i18n="...">Label</span>
       </a>

   TO ADD A PAGE to the bar: copy one nav <a> into the header of each page,
   point it at the new URL and give its <i> one of the modifier classes below.
   TO REMOVE ONE: delete its <a>. Nothing else changes - spacing, the mobile
   drawer and the underline all come from these rules.
   TO ADD A NEW ICON: it must exist in the sprite; add a modifier class with
   its offset (rows are 0, -30, -60, -90, -119, -150, -181, -212; the white
   column is at -358/-360, the green one 30px further right).

   Discord has no icon in the 2016 sprite, so it is masked from
   assets/nav-discord.svg and takes the same two colours.
   =========================================================================== */

.site-navigation a {
  gap: 9px;
}

.nav-ico {
  flex: 0 0 22px;
  width: 22px;
  height: 22px;
  background-repeat: no-repeat;
  background-image: url("assets/nav-sprite.webp");
  background-position: -360px 1px;   /* overridden per icon below */
}

/* resting (white column) */
.nav-ico--home        { background-position: -360px 1px; }
.nav-ico--news        { background-position: -360px -29px; }
.nav-ico--tournaments { background-position: -358px -59px; }
.nav-ico--forum       { background-position: -360px -89px; }
.nav-ico--wiki        { background-position: -357px -118px; }
.nav-ico--ratings     { background-position: -358px -211px; }

/* hover / current page (green column, 30px to the right) */
.site-navigation a:hover .nav-ico--home,
.site-navigation a.is-active .nav-ico--home        { background-position: -390px 1px; }
.site-navigation a:hover .nav-ico--news,
.site-navigation a.is-active .nav-ico--news        { background-position: -390px -29px; }
.site-navigation a:hover .nav-ico--tournaments,
.site-navigation a.is-active .nav-ico--tournaments { background-position: -388px -59px; }
.site-navigation a:hover .nav-ico--forum,
.site-navigation a.is-active .nav-ico--forum       { background-position: -390px -89px; }
.site-navigation a:hover .nav-ico--wiki,
.site-navigation a.is-active .nav-ico--wiki        { background-position: -388px -118px; }
.site-navigation a:hover .nav-ico--ratings,
.site-navigation a.is-active .nav-ico--ratings     { background-position: -388px -211px; }

/* Discord: masked SVG, same two colours as the sprite icons */
.nav-ico--discord {
  background-image: none;
  background-color: var(--discord-light);
  -webkit-mask: url("assets/nav-discord.svg") no-repeat center / 22px 22px;
  mask: url("assets/nav-discord.svg") no-repeat center / 22px 22px;
}

.site-navigation a:hover .nav-ico--discord,
.site-navigation a.is-active .nav-ico--discord {
  background-color: #ffffff;
}

.site-navigation a.nav-discord:hover {
  background-color: var(--discord);
  box-shadow: none;
  color: #ffffff;
}

/* Seven items plus icons need more room than five plain words did, so the
   tracking and padding come in a little between the mobile breakpoint and a
   wide desktop. */
@media (min-width: 981px) {
  .site-navigation a {
    padding: 0 11px;
    font-size: 0.86rem;
    letter-spacing: 0.06em;
  }

  [lang="ka"] .site-navigation a,
  [lang="ru"] .site-navigation a {
    padding: 0 9px;
    font-size: 0.82rem;
    letter-spacing: 0.02em;
  }

}

/* Narrow laptops: labels stay, spacing tightens once more. */
@media (min-width: 981px) and (max-width: 1150px) {
  /* At full size the wordmark needs ~220px and its grid column gets ~190px
     here, so "PRIME TANKI" broke onto two lines on every 1024px laptop, in
     every language. Smaller and tighter keeps it one line (~170px). */
  .wordmark {
    font-size: 1.05rem;
    letter-spacing: 0.3em;
    white-space: nowrap;
  }

  .site-navigation a {
    padding: 0 8px;
    font-size: 0.8rem;
    letter-spacing: 0.02em;
  }

  .nav-ico {
    flex-basis: 20px;
    width: 20px;
    height: 20px;
  }
}

/* In the mobile drawer the icons sit in a fixed column so the labels line up. */
@media (max-width: 980px) {
  .site-navigation a {
    gap: 14px;
  }

  .nav-ico {
    flex-basis: 24px;
    width: 24px;
    height: 24px;
  }
}

/* Georgian, Russian and Armenian set longer words than English caps, so on
   laptops between the mobile breakpoint and ~1150px they tighten further -
   without this the bar runs under the language switcher. */
@media (min-width: 981px) and (max-width: 1150px) {
  [lang="ka"] .site-navigation a,
  [lang="ru"] .site-navigation a,
  [lang="hy"] .site-navigation a {
    gap: 6px;
    padding: 0 6px;
    font-size: 0.74rem;
    letter-spacing: 0.01em;
  }

  [lang="ka"] .nav-ico,
  [lang="ru"] .nav-ico,
  [lang="hy"] .nav-ico {
    flex-basis: 18px;
    width: 18px;
    height: 18px;
  }
}
