/* thefinal landing — dark-sporty, consistent with the game SPA tokens */
:root {
  --bg: #0a0e12;
  --bg-elev: #121820;
  --bg-elev-2: #1a222c;
  --border: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.14);
  --text: #eaf1f4;
  --text-muted: #8593a0;
  --accent: #c8f751;
  --accent-ink: #0a0e12;
  --live: #ff5a4d;
  /* A lost call is its own signal, softer than --live: on one card a running
     prediction and a lost one must never read as the same red. */
  --negative: #ef8377;
  --radius: 14px;
  --radius-lg: 20px;
  --font-display: 'Bricolage Grotesque', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Archivo', ui-sans-serif, system-ui, sans-serif;
  --shadow-card: 0 18px 50px rgba(0, 0, 0, 0.45);
  --wrap: 1120px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

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

body {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

a { color: inherit; }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: clamp(20px, 5vw, 40px); }

.skip-link {
  position: absolute; left: -999px; top: 0; z-index: 100;
  background: var(--accent); color: var(--accent-ink);
  padding: 10px 16px; border-radius: 0 0 10px 0; font-weight: 700;
}
.skip-link:focus { left: 0; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}
.site-header__inner { display: flex; align-items: center; gap: 24px; height: 64px; }
.site-header__brand { display: inline-flex; align-items: center; gap: 8px; }
.wordmark {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-display); font-weight: 800; font-size: 1.35rem;
  letter-spacing: -0.03em; text-decoration: none; color: var(--text);
}
/* The mark (static/logo-mark.svg): our own artwork, decorative beside the name. */
.wordmark__mark { display: block; width: 33px; height: 28px; flex: none; }
.wordmark__accent { color: var(--accent); }
.site-nav { display: none; gap: 24px; }
.site-nav a {
  white-space: nowrap;
  text-decoration: none; color: var(--text-muted); font-weight: 500; font-size: 0.95rem;
  transition: color 0.18s ease;
}
.site-nav a:hover { color: var(--text); }
/* CTA is flush-right on mobile (nav hidden); on desktop the nav takes the auto
   push and the CTA trails it with a fixed gap. */
.site-header .btn { margin-left: auto; }

/* 1000, not 860: a full nav in a longer language (French, with the language
   switcher) does not fit a ~900px header; the menu toggle serves below it. */
@media (min-width: 1000px) {
  .site-nav { display: flex; margin-left: auto; align-items: center; }
  .site-header .btn { margin-left: 28px; }
}
/* Between 1000 and 1299 px the longest navs (Armenian ran 92 px over at
   1040) get tighter gaps, a hair smaller type and the CTA's short label
   rather than pushing the CTA off the edge. */
@media (min-width: 1000px) and (max-width: 1299px) {
  .site-nav { gap: 18px; }
  .site-nav a, .site-nav .menu__trigger { font-size: 0.88rem; }
  .site-header .btn { margin-left: 18px; }
  .site-header .cta-label--long { display: none; }
  .site-header .cta-label--short { display: inline; }
}

/* At 320px the brand + badge + CTA + toggle row runs ~16px past the wrap, and
   body{overflow-x:hidden} would clip the toggle rather than scroll to it. The
   badge is not what gives way — it is a promise, and the smallest phone is
   owed it too — so the nav gaps do. Clear from 344px up. */
@media (max-width: 343px) {
  .site-header__inner { gap: 12px; }
  .site-header__toggle { margin-left: 4px; }
  /* A longer language's short label ("Spielen") still ran 8px past at 320. */
  .site-header .btn--sm { padding-inline: 12px; }
}

/* ---------- Leagues mega-menu ---------- */
.menu { position: relative; }
.menu__trigger {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  background: transparent; border: none; padding: 0;
  font-family: var(--font-body); font-weight: 500; font-size: 0.95rem;
  color: var(--text-muted); cursor: pointer; transition: color 0.18s ease;
}
.menu__trigger:hover, .menu:hover .menu__trigger, .menu:focus-within .menu__trigger { color: var(--text); }
.menu__trigger::after {
  content: ''; width: 0; height: 0; margin-top: 2px;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
}
.menu__panel {
  position: absolute; top: calc(100% + 16px); left: 50%; transform: translateX(-50%);
  z-index: 60; display: flex; gap: 32px; min-width: 380px;
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card); padding: 22px;
}
/* Invisible bridge filling the 16px gap between trigger and panel. Without it,
   the pointer crosses a dead zone on its way down — :hover drops and the panel
   hides before the cursor reaches a league link. The ::before is a descendant
   of .menu, so hovering it keeps .menu:hover (and the panel) alive. */
.menu__panel::before {
  content: ''; position: absolute; top: -16px; left: 0; right: 0; height: 16px;
}
/* Progressive enhancement: without JS, hover/focus-within reveals the panel
   even though [hidden] is present; with JS, the script flips the hidden
   attribute directly and this rule is moot (panel already shown/removed). */
.menu__panel[hidden] { display: none; }
/* Only WITHOUT the script: once menu.js runs it owns `hidden` and
   aria-expanded, and these rules would keep a panel the script just closed on
   screen while focus or the pointer is still inside — a click on the trigger,
   or Escape (which returns focus to it), could never close it. */
:root:not(.js-menus) .menu:hover .menu__panel[hidden],
:root:not(.js-menus) .menu:focus-within .menu__panel[hidden] { display: flex; }
.menu__col { min-width: 160px; }
.menu__heading {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-display); font-weight: 700; font-size: 0.85rem;
  letter-spacing: 0.01em; color: var(--text); margin-bottom: 10px;
}
.menu__list { list-style: none; display: flex; flex-direction: column; gap: 6px; }
.menu__list a {
  display: inline-flex; align-items: center; gap: 6px;
  text-decoration: none; color: var(--text-muted); font-size: 0.92rem; font-weight: 500;
  transition: color 0.18s ease;
}
.menu__list a:hover { color: var(--accent); }
.menu__live { color: var(--live); font-size: 0.6rem; line-height: 1; }
.menu__col--disabled { opacity: 0.55; }
.menu__note { font-size: 0.85rem; color: var(--text-muted); max-width: 20ch; }
.pill {
  display: inline-flex; align-items: center; font-family: var(--font-body);
  font-weight: 700; font-size: 0.62rem; letter-spacing: 0.04em; text-transform: uppercase;
  border-radius: 999px; padding: 2px 8px;
}
.pill--soon { background: var(--bg-elev-2); color: var(--text-muted); border: 1px solid var(--border-strong); }
/* Alpha is a live claim about the product, not a greyed-out "not yet" like
   --soon: accent-tinted so it reads as current, but only tinted, so it does not
   compete with the accent CTA at the other end of the same header. */
.pill--alpha {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
  text-decoration: none;
}
.pill--alpha:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }

/* ---------- Language switcher (ADR-0030) ---------- */
.flag { width: 20px; height: 15px; flex: none; border-radius: 2px; object-fit: cover; box-shadow: 0 0 0 1px var(--border); }
.lang-trigger { gap: 8px; }
.lang-trigger__code {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; color: var(--text-muted);
}
/* Centred under its trigger, like the Tables menu. With thirty-odd languages
   the list runs two columns and scrolls inside a bounded panel rather than
   past the bottom of the window. */
.menu__panel--lang { min-width: 0; padding: 12px; max-height: min(70vh, 560px); overflow-y: auto; }
.menu__panel--lang .lang-list { display: grid; grid-template-columns: repeat(2, minmax(max-content, 1fr)); column-gap: 4px; }
.lang-list { list-style: none; display: flex; flex-direction: column; gap: 2px; width: 100%; margin: 0; padding: 0; }
.lang-list a, .site-footer__langs a { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.lang-list a { padding: 8px 10px; border-radius: 8px; color: var(--text-muted); font-size: 0.92rem; font-weight: 500; }
.lang-list a:hover { background: var(--bg-elev-2); color: var(--text); }
.lang-list a[aria-current="page"] { color: var(--text); font-weight: 600; }
.lang__name { flex: 1; white-space: nowrap; }
/* The CTA's short label is for phones only (see the header template). */
.cta-label--short { display: none; }
@media (max-width: 419px) {
  .site-header .cta-label--long { display: none; }
  .site-header .cta-label--short { display: inline; }
  .site-header .wordmark { gap: 5px; }
  .site-header .wordmark__mark { width: 26px; height: 22px; }
}
/* Below 380px the header holds the name, the Alpha pill, the CTA and the menu
   toggle with nothing to spare in the longer languages: the mark gives way. */
@media (max-width: 379px) {
  .site-header .wordmark__mark { display: none; }
}

/* ---------- Mobile nav disclosure ---------- */
.site-header__toggle {
  display: none; align-items: center; justify-content: center;
  width: 40px; height: 40px; margin-left: 10px; flex: none;
  background: transparent; border: 1px solid var(--border-strong); border-radius: 10px;
  color: var(--text); cursor: pointer;
}
.site-header__toggle-bars,
.site-header__toggle-bars::before,
.site-header__toggle-bars::after {
  content: ''; display: block; width: 18px; height: 2px; background: currentColor; border-radius: 2px;
}
.site-header__toggle-bars { position: relative; }
.site-header__toggle-bars::before { position: absolute; top: -6px; left: 0; }
.site-header__toggle-bars::after { position: absolute; top: 6px; left: 0; }

@media (max-width: 999px) {
  .site-header__toggle { display: inline-flex; }

  /* Its own scroll: the nav hangs from a sticky header, so a list taller than
     the screen (forty languages) would move with the page and never reveal
     its lower half. */
  .site-nav.site-nav--open {
    max-height: calc(100dvh - 64px); overflow-y: auto; overscroll-behavior: contain;
    display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
    position: absolute; top: 64px; left: 0; right: 0;
    background: var(--bg-elev); border-bottom: 1px solid var(--border);
    padding: 16px clamp(20px, 5vw, 40px) 24px;
    box-shadow: var(--shadow-card);
  }
  .site-nav.site-nav--open a { padding: 8px 0; }
  .site-nav.site-nav--open .menu { width: 100%; }
  .site-nav.site-nav--open .menu__trigger { padding: 8px 0; }
  .site-nav.site-nav--open .menu__panel {
    position: static; transform: none; z-index: auto;
    width: 100%; min-width: 0; box-shadow: none; border: none;
    background: transparent; padding: 4px 0 8px 12px; margin: 0;
  }
  /* No hover on touch, and the panel is in-flow here — the bridge would just be
     a stray transparent strip that could swallow taps. */
  .site-nav.site-nav--open .menu__panel::before { content: none; }
  /* The open nav lists the languages in full: no trigger to tap first. */
  .site-nav.site-nav--open .menu--lang { border-top: 1px solid var(--border); margin-top: 8px; padding-top: 8px; }
  .site-nav.site-nav--open .menu--lang .menu__trigger { display: none; }
  .site-nav.site-nav--open .menu--lang .menu__panel[hidden] { display: flex; }
  /* In the phone nav the list is in-flow and one column; the nav scrolls. */
  .site-nav.site-nav--open .menu__panel--lang { max-height: none; overflow: visible; }
  .site-nav.site-nav--open .menu__panel--lang .lang-list { grid-template-columns: 1fr; }
  .site-nav.site-nav--open .lang-list a { padding: 8px 0; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-body); font-weight: 700; font-size: 1rem;
  padding: 14px 24px; border-radius: 999px; text-decoration: none;
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  transition: transform 0.16s ease, background 0.18s ease, border-color 0.18s ease;
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--accent); color: var(--accent-ink); }
.btn--primary:hover { background: #d6ff6b; transform: translateY(-2px); }
.btn--ghost { background: transparent; color: var(--text); border-color: var(--border-strong); }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }
.btn--sm { padding: 9px 18px; font-size: 0.9rem; }
.btn--lg { padding: 17px 34px; font-size: 1.1rem; }
/* A large CTA may wrap on a phone: nowrap is right for an English "Play free",
   wrong for "Joue à thefinal gratuitement", which ran past a 320px screen. */
@media (max-width: 419px) {
  .btn:not(.btn--sm) { white-space: normal; text-align: center; }
}

/* ---------- Shared section bits ---------- */
.section { padding-block: clamp(64px, 10vw, 120px); }
.section--alt { background: var(--bg-elev); border-block: 1px solid var(--border); }
.section__head { max-width: 640px; margin-bottom: clamp(36px, 6vw, 56px); }
.kicker {
  display: inline-block; font-weight: 700; font-size: 0.78rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--accent); margin-bottom: 14px;
}
.section__title {
  font-family: var(--font-display); font-weight: 800; letter-spacing: -0.03em; line-height: 1.05;
  font-size: clamp(1.9rem, 4.5vw, 3rem);
}
.section__lede { margin-top: 16px; color: var(--text-muted); font-size: 1.08rem; max-width: 56ch; }

/* ---------- Hero ---------- */
.hero { position: relative; padding-top: clamp(48px, 8vw, 88px); padding-bottom: clamp(56px, 9vw, 104px); overflow: hidden; }
.hero__glow {
  position: absolute; inset: -30% -10% auto -10%; height: 720px; z-index: 0; pointer-events: none;
  background:
    radial-gradient(60% 55% at 22% 18%, rgba(200, 247, 81, 0.16), transparent 70%),
    radial-gradient(45% 45% at 82% 12%, rgba(43, 108, 255, 0.14), transparent 70%);
  filter: blur(8px);
}
.hero__inner {
  position: relative; z-index: 1;
  display: grid; gap: clamp(40px, 6vw, 64px); align-items: center;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 940px) { .hero__inner { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); } }

.eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-weight: 600; font-size: 0.85rem; color: var(--text-muted);
  border: 1px solid var(--border-strong); border-radius: 999px; padding: 7px 15px; margin-bottom: 22px;
}
.eyebrow__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px rgba(200, 247, 81, 0.15); }
/* A long compound ("voetbalwedstrijden") at headline size can outgrow a
   phone column; it breaks (hyphenated where the language allows) instead. */
.hero__title {
  overflow-wrap: break-word; hyphens: auto;
  font-family: var(--font-display); font-weight: 800; letter-spacing: -0.04em; line-height: 1;
  font-size: clamp(2.2rem, 6vw, 3.6rem);
}
.hl { color: var(--accent); }
/* The turning phrase in the headline (index.html's rotator script). Every
   phrase is in the page, stacked in ONE grid cell: the cell takes the widest
   and tallest of them in this language, so a turn never moves the headline,
   the lede or the card beside it — in Russian the phrases differ by a third
   of their width, and a box that followed each one shifted the whole hero.
   A phrase longer than the column wraps inside the cell rather than running
   off a phone. The box is clipped so the leaving and arriving phrases only
   show inside it; padding and a matching negative margin give descenders
   room under the title's tight line-height. */
.rotator {
  display: inline-grid; vertical-align: top; overflow: hidden;
  padding-bottom: 0.14em; margin-bottom: -0.14em;
}
/* opacity, not visibility: visibility would drop the first phrase from the
   accessibility tree while another shows, leaving the h1 without its end. The
   first phrase is the h1's text throughout; the others are aria-hidden. */
.rotator__word { grid-area: 1 / 1; opacity: 0; }
.rotator__word.is-current, .rotator__word.is-out { opacity: 1; }
.rotator__word.is-in { animation: rotIn 480ms cubic-bezier(0.22, 0.68, 0.3, 1) both; }
.rotator__word.is-out { animation: rotOut 480ms cubic-bezier(0.55, 0, 0.7, 0.4) both; }
@keyframes rotIn { from { transform: translateY(100%); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes rotOut { from { transform: none; opacity: 1; } to { transform: translateY(-100%); opacity: 0; } }
.hero__lede { margin-top: 22px; font-size: clamp(1.05rem, 2.2vw, 1.22rem); color: var(--text-muted); max-width: 52ch; }
.hero__actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 30px; }
.hero__note { margin-top: 18px; font-size: 0.85rem; color: var(--text-muted); }

/* Match card mock */
.hero__card { display: flex; justify-content: center; }
.matchcard {
  width: 100%; max-width: 420px; background: linear-gradient(180deg, var(--bg-elev-2), var(--bg-elev));
  border: 1px solid var(--border-strong); border-radius: var(--radius-lg); padding: 20px;
  box-shadow: var(--shadow-card);
}
.matchcard__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.livebadge { display: inline-flex; align-items: center; gap: 8px; color: var(--live); font-weight: 700; font-size: 0.82rem; letter-spacing: 0.02em; }
.livebadge__pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--live); animation: pulse 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .livebadge__pulse { animation: none; } }
@keyframes pulse { 0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(255, 90, 77, 0.5); } 50% { opacity: 0.6; box-shadow: 0 0 0 6px rgba(255, 90, 77, 0); } }
.matchcard__comp { color: var(--text-muted); font-size: 0.82rem; }
.matchcard__score { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px; margin-bottom: 18px; }
.team { display: flex; align-items: center; gap: 10px; min-width: 0; }
/* Names pulled in against the scoreline, badges pinned to the outer edges. With
   the names left at their natural widths the columns are equal but their
   CONTENT is not — "Real Madrid" filled its 147px while "Man City" left 18px of
   air on the side facing the score, so the score read as sitting nearer Madrid.
   Letting each name span the rest of its column and aligning its text inward
   makes both names touch the score, whatever they are called. */
.team__name { flex: 1; text-align: right; }
.team--right .team__name { text-align: left; }
/* Below ~600px the three-column scoreline leaves each club ~44px and ellipses
   the name away. The name beside the code is not decoration — it is what
   ADR-0012's referential-use argument rests on, "on every surface" — so the
   card takes the shape the live board already uses down here: clubs stacked,
   the scoreline beside them, both names rendered whole. */
@media (max-width: 600px) {
  .matchcard__score { grid-template-columns: 1fr auto; row-gap: 10px; }
  .matchcard__score > div:first-of-type { grid-area: 1 / 1; }
  .matchcard__score > div:last-of-type { grid-area: 2 / 1; }
  .matchcard__score > .score { grid-area: 1 / 2 / span 2; }
  .matchcard__score .team--right { flex-direction: row-reverse; justify-content: flex-end; }
  /* Pulling the names inward is a three-column idea and it does not survive the
     stack: with the clubs on their own rows there is no score between them to
     be equidistant from, and a name still filling its column floated away from
     its own badge — Real Madrid's sat 89px clear of RMA while Man City's hugged
     MCI, so the two rows no longer lined up. Down here each name is just wide
     enough for itself, beside its code. */
  .matchcard__score .team__name { flex: 0 1 auto; text-align: left; }
}
.team--right { justify-content: flex-end; }
.team__name { font-weight: 600; font-size: 0.98rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The badge is a wordmark chip, not a crest: a three-letter club code over the
   club's own two-stop gradient. Deliberately rectangular — a square reads as a
   badge outline and cramps three characters; the wide chip is also visibly not
   a crest, which is the shape ADR-0012 wants. Ink is fixed dark because every
   colour is clamped into a light band at ingest. */
.badge {
  flex: none; width: 56px; height: 38px; border-radius: 11px; display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 800; font-size: 0.95rem; letter-spacing: 0.02em;
  color: #0a0e12; background: linear-gradient(140deg, var(--c1), var(--c2));
}
/* A licensed crest (ADR-0027) keeps the wordmark chip's OUTER box at every size,
   so a board of mixed clubs — some imported, some not — has no ragged edge and
   nothing moves when an import lands or a takedown removes one. Inside that box
   it is drawn bare: no gradient (the club colour has already done its job on
   every badge with no image), no frame, no padding, because the chip is a wide
   rectangle and a crest is roughly square — every pixel spent on a border is a
   pixel off the artwork's height, which is all the height it gets. */
.badge--crest { background: none; border: 0; padding: 0; display: flex; align-items: center; justify-content: center; }
/* contain, never cover: a crest is artwork with its own aspect ratio, and
   cropping a mark is a modification of it. In a wide box a square crest is
   centred at the row's full height, which is the largest it can legibly be. */
.badge__crest { height: 100%; width: auto; max-width: 100%; object-fit: contain; display: block; }
.score { font-family: var(--font-display); font-weight: 800; font-size: 1.7rem; letter-spacing: -0.02em; }
/* The hero timeline: the match drawn the way the game's own match timeline
   draws it (frontend moments-timeline.scss) — a minute column with a thin
   connector running down it, one full-width row per item, the row outlined by
   its verdict. Newest at the top.

   The box is a FIXED height of exactly heroTimelineRows items (hero.go), and
   every item is exactly one row tall — text truncates rather than wraps — so
   nothing on the card can change its height while it plays. A new item grows
   in at the top and the oldest is pushed out of the clipped bottom. */
.htl {
  --htl-row: 32px; --htl-gap: 5px; --htl-min: 2.6rem;
  position: relative; list-style: none; margin: 0; padding: 16px 0 0;
  border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: var(--htl-gap);
  height: calc(16px + 10 * var(--htl-row) + 9 * var(--htl-gap));
  overflow: hidden;
}
/* The connector, down the minute column and behind the rows. */
.htl::before {
  content: ''; position: absolute; top: 16px; bottom: 0; left: calc(var(--htl-min) / 2); width: 1px;
  background: var(--border-strong);
}
.htl__row, .htl__phase { flex: none; height: var(--htl-row); box-sizing: border-box; position: relative; }
/* The left rule takes the verdict's colour and the glyph says the same thing,
   so nothing here is colour alone. */
.htl__row {
  display: grid; grid-template-columns: var(--htl-min) minmax(0, 1fr) auto auto; align-items: center; column-gap: 8px;
  padding-right: 10px; border: 1px solid var(--border); border-left-width: 3px; border-radius: 10px;
  background: var(--bg-elev); font-size: 0.84rem;
}
.htl__row[data-status='landed'] { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); border-left-color: var(--accent); }
.htl__row[data-status='missed'] { border-color: color-mix(in srgb, var(--negative) 40%, var(--border)); border-left-color: var(--negative); }
.htl__min {
  justify-self: center; padding: 0 3px; background: var(--bg-elev);
  font-family: var(--font-display); font-weight: 800; font-size: 0.84rem; white-space: nowrap;
}
.htl__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The rows are fixed-height (the replay scrolls by row), so a long label cannot
   wrap; on the narrowest phones it gets a little more room instead, enough for
   "Exaktes Ergebnis 2–1" to keep its score. */
@media (max-width: 359px) {
  .htl__row { font-size: 0.78rem; column-gap: 6px; }
}
.htl__row[data-kind='goal'] .htl__text, .htl__row[data-kind='card'] .htl__text { font-weight: 700; }
.htl__row[data-kind='card'] .htl__text::after {
  content: ''; display: inline-block; width: 8px; height: 11px; margin-left: 7px; border-radius: 2px;
  background: #f5c542; vertical-align: -1px;
}
.htl__pill {
  grid-column: 3; padding: 0 8px; border: 1px solid var(--border); border-radius: 999px; background: var(--bg-elev-2);
  font-family: var(--font-display); font-weight: 700; font-size: 0.78rem; white-space: nowrap;
}
.htl__pts { grid-column: 4; font-family: var(--font-display); font-weight: 700; white-space: nowrap; color: var(--accent); }
.htl__row[data-status='missed'] .htl__pts { color: var(--negative); }
/* A phase line: Kick-off / Half-time / Full-time with the score beside it,
   the connector running through. */
.htl__phase { display: flex; justify-content: center; align-items: center; gap: 8px; }
.htl__phase-label, .htl__phase-score {
  padding: 1px 10px; border-radius: 999px; background: var(--bg-elev-2);
  font-size: 0.72rem; font-weight: 800; letter-spacing: 0.04em;
}
.htl__phase-score { color: var(--text-muted); font-weight: 700; }
/* The arrival: the new item grows from nothing at the top — pulling in the
   gap it will sit behind — and fades in, which slides everything below it
   down one row. The list itself never resizes. */
.htl__row.is-new, .htl__phase.is-new { animation: htlIn 380ms cubic-bezier(0.22, 0.68, 0.3, 1) both; }
@keyframes htlIn {
  from { height: 0; margin-top: calc(-1 * var(--htl-gap)); opacity: 0; }
  to { height: var(--htl-row); margin-top: 0; opacity: 1; }
}
/* A number that has just changed gets one beat of emphasis rather than a
   count-up: the Score is the thing the card is about, and a value that merely
   swaps is easy to miss between two rows arriving. */
.is-bumped { animation: bump 460ms ease-out both; }
@keyframes bump { 0% { transform: none; } 30% { transform: scale(1.14); } 100% { transform: none; } }
/* Reduced motion: no travel, no bump. The card still plays — items appear and
   numbers change — because the content IS the message; only the movement goes.
   Same bargain the reveal script and the live pulse already make on this page. */
@media (prefers-reduced-motion: reduce) {
  .htl__row.is-new, .htl__phase.is-new, .is-bumped { animation: none; }
}
.matchcard__foot { display: flex; align-items: center; justify-content: space-between; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); font-size: 0.9rem; }
.matchcard__foot strong { font-family: var(--font-display); color: var(--accent); }
.rankjump { color: var(--accent); font-weight: 700; font-size: 0.85rem; }

/* ---------- Steps ---------- */
.steps { list-style: none; display: grid; gap: 18px; grid-template-columns: 1fr; counter-reset: step; }
@media (min-width: 760px) { .steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.step {
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 28px 24px; position: relative; overflow: hidden;
}
.step::before { content: ''; position: absolute; inset: 0 0 auto 0; height: 3px; background: linear-gradient(90deg, var(--accent), transparent 60%); opacity: 0.6; }
.step__num { font-family: var(--font-display); font-weight: 800; font-size: 2.4rem; color: var(--bg-elev-2); -webkit-text-stroke: 1px var(--border-strong); }
.step__title { font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; margin: 10px 0 8px; letter-spacing: -0.01em; }
.step p { color: var(--text-muted); }

/* ---------- Predictions grid ---------- */
/* minmax(0, 1fr), not 1fr: a bare 1fr track never shrinks below its longest
   word, and a longer language's word ("remplacement") pushed the two phone
   columns past the screen edge. Same on every multi-column grid below. */
.qgrid { display: grid; gap: 16px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 720px) { .qgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.qcard {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 22px 20px; transition: transform 0.18s ease, border-color 0.18s ease;
}
.section--alt .qcard { background: var(--bg-elev-2); }
.qcard:hover { transform: translateY(-3px); border-color: var(--border-strong); }
.qcard__pts {
  display: inline-block; font-family: var(--font-display); font-weight: 800; font-size: 1.05rem;
  color: var(--accent-ink); background: var(--accent); border-radius: 8px; padding: 3px 10px; margin-bottom: 14px;
}
.qcard--soon .qcard__pts { background: var(--bg-elev); color: var(--text-muted); border: 1px solid var(--border-strong); }
.qcard h3 { font-family: var(--font-display); font-weight: 700; font-size: 1.12rem; margin-bottom: 6px; hyphens: auto; overflow-wrap: break-word; }
.qcard p { color: var(--text-muted); font-size: 0.94rem; }

/* ---------- Feature (leagues) ---------- */
.feature { display: grid; gap: clamp(36px, 6vw, 60px); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .feature { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.ticks { list-style: none; margin: 22px 0 30px; display: grid; gap: 12px; }
.ticks li { position: relative; padding-left: 30px; color: var(--text); }
.ticks li::before {
  content: '✓'; position: absolute; left: 0; top: 0; width: 20px; height: 20px; border-radius: 50%;
  background: rgba(200, 247, 81, 0.16); color: var(--accent); font-size: 0.72rem; font-weight: 800;
  display: grid; place-items: center;
}
.pts { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.01em; }

/* ---------- Pillars ---------- */
.pillars { display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 760px) { .pillars { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.pillar { background: var(--bg); border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: var(--radius); padding: 24px; }
.section--alt .pillar { background: var(--bg-elev-2); }
.pillar h3 { font-family: var(--font-display); font-weight: 700; font-size: 1.18rem; margin-bottom: 8px; }
.pillar p { color: var(--text-muted); font-size: 0.96rem; }

/* ---------- Final CTA ---------- */
.cta-band { padding-block: clamp(64px, 11vw, 128px); text-align: center; position: relative; overflow: hidden; }
.cta-band::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(50% 120% at 50% 0%, rgba(200, 247, 81, 0.12), transparent 60%);
}
.cta-band__inner { position: relative; z-index: 1; }
.cta-band h2 { font-family: var(--font-display); font-weight: 800; letter-spacing: -0.03em; line-height: 1.05; font-size: clamp(2rem, 6vw, 3.4rem); max-width: 16ch; margin-inline: auto; }
.cta-band p { color: var(--text-muted); font-size: 1.1rem; margin: 18px 0 30px; }

/* ---------- Footer ---------- */
.site-footer { border-top: 1px solid var(--border); background: var(--bg-elev); }
.site-footer__inner { display: grid; gap: 28px; padding-block: 48px 28px; grid-template-columns: 1fr; }
@media (min-width: 720px) { .site-footer__inner { grid-template-columns: 1fr 1.4fr; } }
.site-footer__brand p { color: var(--text-muted); margin-top: 10px; font-size: 0.94rem; }
.site-footer__disclaimer p { color: var(--text-muted); font-size: 0.9rem; margin-bottom: 8px; max-width: 60ch; }
.site-footer__disclaimer strong { color: var(--text); }
.site-footer__base { display: flex; align-items: center; justify-content: space-between; padding-block: 20px; border-top: 1px solid var(--border); color: var(--text-muted); font-size: 0.86rem; }
.site-footer__base a { color: var(--accent); text-decoration: none; }
/* The language switcher (ADR-0030): a quiet row above the base line, wrapping
   on narrow screens; the current language is plain text-colour, not a link
   colour, so it reads as "you are here". */
.site-footer__langs ul { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 0; padding: 0 0 16px; list-style: none; font-size: 0.86rem; }
.site-footer__langs a { color: var(--text-muted); gap: 8px; }
.site-footer__langs a:hover { color: var(--accent); }
.site-footer__langs a[aria-current="page"] { color: var(--text); font-weight: 600; }

/* ---------- Live scoreboard ---------- */
.board__tabs { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 12px; margin-bottom: 20px; scrollbar-width: none; }
.board__tabs::-webkit-scrollbar { display: none; }
.board__tab {
  flex: none; font-family: var(--font-body); font-weight: 600; font-size: 0.9rem;
  color: var(--text-muted); background: var(--bg-elev); border: 1px solid var(--border);
  border-radius: 999px; padding: 9px 16px; cursor: pointer; white-space: nowrap;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.board__tab:hover { color: var(--text); }
.board__tab.is-active { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
.board__league { margin-bottom: 26px; }
.board__league-name {
  font-family: var(--font-display); font-weight: 700; font-size: 1.02rem; letter-spacing: -0.01em;
  color: var(--text-muted); padding: 0 4px 10px; border-bottom: 1px solid var(--border); margin-bottom: 6px;
}
.board__list { list-style: none; display: grid; gap: 4px; }
.board__empty { color: var(--text-muted); padding: 24px 4px; }
.match {
  display: grid; align-items: center; gap: 12px; padding: 12px 8px; border-radius: var(--radius);
  grid-template-columns: 58px minmax(0, 1fr) auto auto; transition: background 0.15s ease;
}
.match:hover { background: var(--bg-elev); }
.match__status { font-size: 0.82rem; color: var(--text-muted); text-align: center; }
.match__ko { font-weight: 600; }
.match__live { display: inline-flex; align-items: center; gap: 6px; color: var(--live); font-weight: 700; }
.match__pulse { width: 7px; height: 7px; border-radius: 50%; background: var(--live); animation: pulse 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .match__pulse { animation: none; } }
.match__ft { font-weight: 700; color: var(--text); }
.match__off { color: var(--text-muted); }
.match__teams { display: grid; gap: 6px; min-width: 0; }
.match__team { display: flex; align-items: center; gap: 9px; min-width: 0; }
.match__name { font-weight: 600; font-size: 0.96rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.badge--sm { width: 44px; height: 26px; border-radius: 8px; font-size: 0.76rem; }
/* The standings club cell: badge and name on one line. A table cell cannot be a
   flex container without leaving the table layout, so the badge goes inline. */
.standings__club { white-space: nowrap; }
.standings__club > .badge { display: inline-grid; vertical-align: middle; margin-right: 10px; }
.standings__club > .badge--crest { display: inline-flex; }
.standings__name { vertical-align: middle; }
.match__score { display: grid; gap: 6px; font-family: var(--font-display); font-weight: 800; font-size: 1.05rem; text-align: center; min-width: 24px; color: var(--text-muted); }
.match--live .match__score, .match--finished .match__score { color: var(--text); }
.match__cta { justify-self: end; }
@media (max-width: 560px) {
  .match { grid-template-columns: 50px minmax(0, 1fr) auto; }
  .match__cta { grid-column: 1 / -1; justify-self: stretch; text-align: center; }
}

/* ---------- Reveal animation ---------- */
[data-reveal] { opacity: 0; transform: translateY(18px); transition: opacity 0.6s ease, transform 0.6s ease; }
[data-reveal].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { [data-reveal] { opacity: 1; transform: none; transition: none; } }

/* ---------- Rules / documentation page ---------- */
.rules { padding-block: clamp(28px, 6vw, 56px); }
.rules__layout { display: grid; gap: 40px; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .rules__layout { grid-template-columns: 220px minmax(0, 1fr); gap: 56px; } }

.rules__toc { position: static; }
@media (min-width: 900px) { .rules__toc { position: sticky; top: 88px; } }
.rules__toc-title { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); margin-bottom: 10px; }
.rules__toc ol { list-style: none; display: flex; flex-direction: column; gap: 2px; }
.rules__toc a { display: block; padding: 6px 10px; border-radius: 8px; color: var(--text-muted); text-decoration: none; font-size: 0.92rem; }
.rules__toc a:hover { color: var(--text); background: var(--bg-elev); }

.rules__body { min-width: 0; }
.rules__head { border-bottom: 1px solid var(--border); padding-bottom: 24px; margin-bottom: 8px; }
.rules__h1 { font-family: var(--font-display); font-weight: 800; letter-spacing: -0.03em; line-height: 1.05; font-size: clamp(2rem, 5vw, 3rem); margin: 10px 0 14px; }
.rules__lede { color: var(--text-muted); font-size: 1.05rem; max-width: 62ch; }
.rules__lede strong { color: var(--text); }
.rules__meta { margin-top: 14px; color: var(--text-muted); font-size: 0.9rem; }

.rules__section { padding-block: 26px; border-bottom: 1px solid var(--border); scroll-margin-top: 88px; }
.rules__section:last-of-type { border-bottom: none; }
.rules__section h2 { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.02em; font-size: 1.6rem; margin-bottom: 12px; }
.rules__section h3 { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; margin: 22px 0 8px; scroll-margin-top: 88px; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.rules__section p { color: var(--text-muted); max-width: 68ch; margin-bottom: 10px; }
.rules__section p strong, .rules__section li strong { color: var(--text); }
.rules__section code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.86em; background: var(--bg-elev-2); border: 1px solid var(--border); border-radius: 6px; padding: 1px 6px; color: var(--text); }

.rules__badge { font-family: var(--font-body); font-weight: 700; font-size: 0.72rem; letter-spacing: 0.02em; color: var(--accent-ink); background: var(--accent); border-radius: 999px; padding: 3px 9px; }

.rules__dl { display: grid; gap: 4px 0; margin-top: 6px; }
.rules__dl dt { color: var(--text); font-weight: 600; margin-top: 12px; }
.rules__dl dd { color: var(--text-muted); max-width: 68ch; }

.rules__steps, .rules__ticks { margin: 6px 0 0; padding-left: 22px; color: var(--text-muted); }
.rules__steps li, .rules__ticks li { margin-bottom: 10px; max-width: 68ch; }
.rules__ticks { list-style: none; padding-left: 0; }
.rules__ticks li { position: relative; padding-left: 26px; }
.rules__ticks li::before { content: "✓"; position: absolute; left: 0; top: 0; color: var(--accent); font-weight: 700; }

/* A table wider than a phone scrolls inside its own box: the page itself
   hides horizontal overflow (body overflow-x: hidden), so a wide table would
   otherwise be cut off rather than scrollable. tabindex on the wrapper lets a
   keyboard scroll it too. */
.table-scroll { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }
.table-scroll > .rules__table { margin: 0; }
.table-scroll { margin: 14px 0 4px; }
.rules__table { width: 100%; border-collapse: collapse; margin: 14px 0 4px; font-size: 0.95rem; overflow: hidden; }
.rules__table th, .rules__table td { text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--border); }
.rules__table thead th { color: var(--text-muted); font-weight: 600; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.06em; }
.rules__table tbody th { color: var(--text); font-weight: 600; }
.rules__table .pts { font-family: var(--font-display); font-weight: 800; color: var(--accent); font-size: 1.05rem; }
.rules__table .pts--neg { color: var(--live); }

.rules__cta { padding-top: 28px; }

/* ---------- Legal pages ----------------------------------------------------
   The four legal documents (/privacy, /cookies, /terms, /legal) reuse the
   .rules__* documentation layout rather than cloning forty rules under a
   .legal__* prefix: they are the same kind of page — a table of contents beside
   a long body of prose, tables and definition lists. Only what genuinely
   differs is added here. */

/* /legal is short enough that a sticky table of contents beside it would be a
   nav for four headings — so that page drops the sidebar column. */
.rules__layout--single { grid-template-columns: minmax(0, 1fr); max-width: 760px; }
@media (min-width: 900px) { .rules__layout--single { grid-template-columns: minmax(0, 1fr); } }

/* Footer legal column + the operator line in the base row. */
.site-footer__legal-title { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); margin-bottom: 10px; }
.site-footer__links { list-style: none; display: flex; flex-direction: column; gap: 6px; }
.site-footer__links a { color: var(--text-muted); text-decoration: none; font-size: 0.9rem; }
.site-footer__links a:hover { color: var(--accent); }
@media (min-width: 760px) { .site-footer__inner { grid-template-columns: 1.2fr 1.6fr auto; } }
.site-footer__base { flex-wrap: wrap; gap: 8px 16px; }

/* ---------- Consent banner -------------------------------------------------
   Rendered hidden by the server and revealed by static/consent.js only when
   there is a live choice to make.

   The two buttons are intentionally equal in weight. Making "Accept" the
   visually dominant option is the classic dark pattern that invalidates the
   consent it collects, so .consent__actions gives both children the same box
   and only the standard .btn--primary / .btn--ghost fills distinguish them. */
.consent {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 60;
  background: var(--bg-elev); border-top: 1px solid var(--border-strong);
  box-shadow: 0 -18px 50px rgba(0, 0, 0, 0.45);
}
.consent[hidden] { display: none; }
.consent__inner { display: grid; gap: 16px; padding-block: 18px; align-items: center; }
@media (min-width: 780px) { .consent__inner { grid-template-columns: minmax(0, 1fr) auto; gap: 32px; } }
.consent__text p { color: var(--text-muted); font-size: 0.92rem; max-width: 72ch; }
.consent__text p strong { color: var(--text); }
.consent__text p + p { margin-top: 6px; }
.consent__text a { color: var(--accent); }
.consent__actions { display: flex; gap: 10px; }
.consent__actions .btn { flex: 1 1 auto; min-width: 132px; justify-content: center; }

/* The persistent control on /cookies — same two choices, always reachable, so
   withdrawing consent is no harder than giving it. */
.consent__panel { border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 18px; margin-top: 14px; background: var(--bg-elev); }
.consent__status { color: var(--text); font-weight: 600; margin-bottom: 12px; }
.consent__panel-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.consent__note { color: var(--text-muted); font-size: 0.86rem; margin-top: 12px; max-width: 68ch; }
