/* ==========================================================================
   RIVALZ — Reset, base typography, accessibility primitives
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;   /* iOS: don't inflate text on rotate */
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;         /* clears the sticky header on anchor jumps */
  hanging-punctuation: first last;

  /* DIE SEITE WACKELT NICHT MEHR BEI JEDEM KLICK.

     Gemeldet am 13. September 2026 fuer Abseits: "Im Spiel Imposter wackelt
     die Seite bei jedem Klick." Es lag nicht an dem Spiel.

     Ohne reservierte Rinne blendet der Browser die Bildlaufleiste ein und
     aus, je nachdem ob der Inhalt gerade hoeher ist als das Fenster — und
     mit ihr springt die GANZE Seite um deren Breite zur Seite. Gemessen in
     Abseits: die Dokumenthoehe wechselt von Bildschirm zu Bildschirm
     zwischen 916, 974 und 1022 px, und die Fensterbreite entsprechend
     zwischen 1280 und 1269. Elf Pixel, bei jedem Tippen.

     Abseits faellt es auf, weil dort JEDER Klick den Bildschirm wechselt:
     zehn Rollenkarten, Diskussion, Abstimmung, Ergebnis. Die Ursache ist
     aber allgemein und trifft jedes Spiel, das seine Karte neu zeichnet.

     `stable` haelt die Rinne immer frei. Der Preis sind rund elf Pixel
     Breite auf Seiten, die nicht scrollen — gegen eine Seite, die bei jedem
     Klick springt, ist das kein Preis. */
  scrollbar-gutter: stable;
}

body {
  min-height: 100svh;
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-fg);
  background-color: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-synthesis-weight: none;
  overflow-x: clip;                 /* never a horizontal scrollbar */
  transition: background-color var(--dur-base) var(--ease-out),
              color var(--dur-base) var(--ease-out);
}

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

svg { flex-shrink: 0; }

input, button, textarea, select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }

ul, ol { list-style: none; padding: 0; }

a {
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

/* ---------- Headings ------------------------------------------------------ */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

h1 { font-size: var(--text-5xl); letter-spacing: var(--tracking-tighter); }
h2 { font-size: var(--text-4xl); letter-spacing: var(--tracking-tighter); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl); }

p { text-wrap: pretty; }

/* ---------- Focus: never removed, only restyled --------------------------- */

:focus-visible {
  outline: 2px solid var(--color-ring);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}

:focus:not(:focus-visible) { outline: none; }

/* ---------- Selection ----------------------------------------------------- */

::selection {
  background: var(--color-primary);
  color: var(--color-on-primary);
}

/* ---------- Scrollbar (progressive, ignored where unsupported) ------------ */

@supports (scrollbar-color: auto) {
  html {
    scrollbar-color: var(--color-border-strong) transparent;
    scrollbar-width: thin;
  }
}

/* ---------- [hidden] gilt, und zwar ueberall ------------------------------
   Das `hidden`-Attribut bringt nur ein `display: none` aus dem
   Browser-Standard mit, und JEDE Autorenregel schlaegt das. Wer also
   irgendwo `display: flex` an eine Klasse schreibt, hat `el.hidden = true`
   fuer dieses Element still ausser Kraft gesetzt — kein Fehler, keine
   Warnung, das Element steht einfach weiter da.

   Diese Falle ist in diesem Haus VIERMAL zugeschnappt: .header__login,
   .header__cta, #cta-band und zuletzt .liga-geld, der Geldblock im
   Liga-Formular. Er ist als `hidden` ausgeliefert und wird nur bei "Mit
   Geld" gezeigt — der Kommentar daneben sagt ausdruecklich "Wer 'Spass'
   waehlt, soll die Geldfelder gar nicht erst sehen". Man sah sie trotzdem,
   weil `#game-view .liga-geld { display: flex }` daneben stand.

   Die drei ersten Faelle sind einzeln nachgeruestet worden, in styles.css,
   als Liste von Klassennamen — und die naechste Klasse fehlte darin, wie
   Listen das so an sich haben. Deshalb hier, einmal, fuer alles.

   `!important`, weil es sonst wieder von jeder Klassenregel geschlagen wird:
   das Attribut IST die Aussage "dieses Element ist gerade nicht da", und die
   soll keine Layoutregel umstossen koennen.

   GEMESSEN, bevor die Regel kam: ueber alle zehn Spiele, Katalog, Profil und
   Liga trug genau EIN Element ein `hidden` und wurde trotzdem gemalt —
   .liga-geld. Die Regel repariert also den einen Fall und verhindert den
   naechsten, ohne heute sonst etwas zu bewegen. */
[hidden] { display: none !important; }

/* ---------- Utilities ----------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--md { max-width: var(--container-md); }
.container--sm { max-width: var(--container-sm); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: var(--space-sm);
  left: var(--space-sm);
  z-index: var(--z-toast);
  padding: var(--space-xs) var(--space-md);
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 600;
  transform: translateY(calc(-100% - var(--space-lg)));
  transition: transform var(--dur-fast) var(--ease-out);
}

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

/* ---------- Motion preferences -------------------------------------------
   Honours the OS setting. JS also reads this to skip GSAP timelines. */

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

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Anything JS reveals must still end up visible. */
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* ---------- Off-screen animation pause (set by main.js) ------------------- */

.is-paused,
.is-paused::before,
.is-paused::after { animation-play-state: paused !important; }

/* ---------- No-JS fallback: never leave content hidden -------------------- */

.no-js [data-reveal] { opacity: 1 !important; transform: none !important; }
