:root {
  --blood: #d4141a;
  --blood-hot: #ff2a2a;
  --blood-deep: #6a0b10;
  --velvet: #3a1638;
  --purple: #241028;
  --ink: #10060f;
  --ink-soft: #1c0c1a;
  --bone: #f6ead4;
  --bone-dim: #c9b59a;
  --gold: #e0b15a;
  --gold-soft: #f3d48a;
  --torch: #ff8a3d;
  --mist: rgba(246, 234, 212, 0.07);
  --line: rgba(224, 177, 90, 0.34);
  --font-display: "Baloo 2", "Nunito", system-ui, sans-serif;
  --font-display-weight: 800;
  --font-body: "Nunito", system-ui, sans-serif;
  --radius: 14px;
  /* The reading column. Every section, the header row, the footer, the consent bar and the sticky
     play bar derive their gutters from this one number, so the site shares a single left edge at
     every width - a wide 1360px stage rather than a 1120px column with dead space beside
     it. */
  --max: 1360px;
  --gutter: max(1rem, calc((100% - var(--max)) / 2));
}

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

html {
  scroll-behavior: smooth;
  /* The menu is fixed and, from 861px up, two rows tall: an in-page jump has to stop short of it or
     the section title lands underneath the bar. */
  scroll-padding-top: 7.4rem;
}

@media (max-width: 860px) {
  /* One compact row on a phone - brand, hamburger, play. */
  html {
    scroll-padding-top: 4.9rem;
  }
}

body {
  margin: 0;
  color: var(--bone);
  background:
    radial-gradient(900px 520px at 80% -8%, rgba(212, 20, 26, 0.28), transparent 58%),
    radial-gradient(720px 480px at 8% 12%, rgba(88, 32, 110, 0.45), transparent 55%),
    linear-gradient(180deg, #1a0a18 0%, var(--ink) 38%, #090407 100%);
  font-family: var(--font-body);
  font-weight: 500;
  line-height: 1.7;
  overflow-x: hidden;
}

body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 40;
  background:
    radial-gradient(120% 80% at 50% 120%, rgba(0, 0, 0, 0.45), transparent 55%);
  box-shadow: inset 0 0 140px 40px rgba(8, 2, 8, 0.55);
}

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

a {
  color: var(--gold-soft);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  color: #fff;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--blood);
  color: #fff;
  padding: 0.75rem 1rem;
  z-index: 1000;
}

.skip-link:focus {
  left: 1rem;
  top: 1rem;
}

.atmosphere {
  pointer-events: none;
  position: fixed;
  inset: 0;
  z-index: 30;
  overflow: hidden;
}

.cobweb {
  position: absolute;
  width: 160px;
  height: 160px;
  opacity: 0.28;
  background:
    radial-gradient(circle at 0 0, transparent 18px, rgba(246, 234, 212, 0.15) 19px, transparent 20px),
    repeating-conic-gradient(from 0deg at 0 0, transparent 0 12deg, rgba(246, 234, 212, 0.18) 12deg 13deg);
}

.cobweb--tl {
  top: -8px;
  left: -8px;
}

.cobweb--tr {
  top: -8px;
  right: -8px;
  transform: scaleX(-1);
}

.bat {
  position: absolute;
  width: 28px;
  height: 12px;
  background: #0a0408;
  clip-path: polygon(0 60%, 18% 0, 38% 48%, 50% 20%, 62% 48%, 82% 0, 100% 60%, 70% 100%, 50% 72%, 30% 100%);
  opacity: 0.45;
  backface-visibility: hidden;
  will-change: transform;
  animation: bat-fly 16s linear infinite;
}

.bat:nth-child(2) {
  width: 18px;
  height: 8px;
  animation-duration: 12s;
  animation-delay: -4s;
  opacity: 0.3;
}

.bat:nth-child(3) {
  width: 22px;
  height: 10px;
  animation-duration: 20s;
  animation-delay: -9s;
  opacity: 0.22;
}

/* Fixed, not absolute: the menu has to stay one tap away however deep the reader has scrolled.
   Deliberately no `backdrop-filter` here - it would turn the header into a containing block for
   its own fixed descendants, and the mobile drawer (`.site-menu`, `position: fixed`) would collapse
   into the header box instead of covering the viewport. The gradient does the legibility work. */
.site-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.3rem 1rem;
  padding: 0.65rem var(--gutter) 0.6rem;
  background: linear-gradient(180deg, rgba(9, 4, 7, 0.97), rgba(9, 4, 7, 0.86));
  border-bottom: 1px solid rgba(224, 177, 90, 0.18);
}

.nav-brand {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  text-decoration: none;
  filter: drop-shadow(0 4px 12px rgba(212, 20, 26, 0.45));
}

.nav-brand img {
  height: 2.15rem;
  width: auto;
  max-width: min(220px, 46vw);
}

.nav-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem 1.25rem;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-links a {
  color: var(--bone-dim);
  text-decoration: none;
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.nav-links a:hover {
  color: var(--gold-soft);
}

.lang-switch {
  display: flex;
  gap: 0.35rem;
}

.lang-switch a {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.28rem 0.5rem;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-decoration: none;
  color: var(--bone-dim);
  background: rgba(16, 6, 15, 0.45);
}

.lang-switch a[aria-current="page"] {
  background: var(--blood);
  border-color: var(--blood);
  color: #fff;
}

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: end;
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  background-color: #10060f;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  /* WebP first (48 KB / 120 KB), JPEG as the fallback: the old single 445 KB JPEG is gone. */
  background-image:
    linear-gradient(180deg, rgba(16, 6, 15, 0.18) 0%, rgba(16, 6, 15, 0.5) 48%, rgba(16, 6, 15, 0.97) 100%),
    url("../assets/images/hero-bg-1600.jpg");
  background-image:
    linear-gradient(180deg, rgba(16, 6, 15, 0.18) 0%, rgba(16, 6, 15, 0.5) 48%, rgba(16, 6, 15, 0.97) 100%),
    -webkit-image-set(
      url("../assets/images/hero-bg-960.webp") 1x,
      url("../assets/images/hero-bg.webp") 2x
    );
  background-image:
    linear-gradient(180deg, rgba(16, 6, 15, 0.18) 0%, rgba(16, 6, 15, 0.5) 48%, rgba(16, 6, 15, 0.97) 100%),
    image-set(url("../assets/images/hero-bg-960.webp") 1x, url("../assets/images/hero-bg.webp") 2x);
  /* A layer of its own, driven by the compositor. The drift animates the translation only (the
     scale used to move as well, which forced Chrome to re-raster a full-viewport image frame after
     frame - the page's biggest source of dropped frames on a phone). */
  transform: scale(1.06) translate3d(0, 0, 0);
  backface-visibility: hidden;
  will-change: transform;
  animation: hero-drift 18s ease-in-out infinite alternate;
}

.hero__veil {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 50% 35%, transparent 0%, rgba(16, 6, 15, 0.28) 55%, rgba(16, 6, 15, 0.82) 100%),
    linear-gradient(90deg, rgba(16, 6, 15, 0.5), transparent 42%, rgba(58, 22, 56, 0.28));
  pointer-events: none;
}

.hero__veil::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 28%;
  background: linear-gradient(180deg, transparent, rgba(212, 20, 26, 0.18));
  mix-blend-mode: multiply;
}

.hero__content {
  position: relative;
  z-index: 2;
  width: min(100% - 2rem, var(--max));
  margin: 0 auto;
  padding: 6.5rem 0 3rem;
}

@media (max-width: 720px) {
  .hero {
    align-items: center;
  }

  /* The header is one compact row on phones now (brand + hamburger), so the hero copy can sit
     higher: the old 8.5rem was reserving room for three rows of wrapped desktop links. */
  .hero__content {
    padding-top: 5.4rem;
  }
}

.hero__logo {
  width: min(640px, 90vw);
  height: auto;
  margin-bottom: 1.1rem;
  filter: drop-shadow(0 10px 0 #3a0508) drop-shadow(0 18px 40px rgba(0, 0, 0, 0.55));
}

@media (max-width: 720px) {
  /* A phone used to get the 2x backdrop - 118 KB for a picture the veil covers most of - while the
     hero screenshot (the largest paint on the page) waited for bandwidth. The 1x file is the whole
     picture at 412px, and the preload in the head matches this rule exactly. */
  .hero__media {
    background-image:
      linear-gradient(180deg, rgba(16, 6, 15, 0.18) 0%, rgba(16, 6, 15, 0.5) 48%, rgba(16, 6, 15, 0.97) 100%),
      url("../assets/images/hero-bg-960.webp");
  }
}

.hero h1 {
  margin: 0 0 0.85rem;
  max-width: 18ch;
  font-family: var(--font-display);
  font-weight: var(--font-display-weight);
  font-size: clamp(2rem, 5.4vw, 3.5rem);
  line-height: 1.08;
  letter-spacing: 0.01em;
  color: #fff7ec;
  text-shadow: 0 2px 0 #5a1018, 0 8px 28px rgba(0, 0, 0, 0.75);
  opacity: 0;
  transform: translateY(18px);
  animation: rise-in 0.55s ease-out forwards 0.12s;
}

/**
 * The banter line, one step down from the intent H1: the H1 names the game, the search terms and
 * the job of the page, this keeps the joke Smokey's marketers wrote for him.
 */
.hero__tagline {
  margin: 0 0 0.9rem;
  max-width: 44ch;
  font-family: var(--font-display);
  font-weight: var(--font-display-weight);
  font-size: clamp(1.05rem, 2.1vw, 1.4rem);
  line-height: 1.25;
  color: #f0c46a;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.75);
  opacity: 0;
  transform: translateY(18px);
  animation: rise-in 0.55s ease-out forwards 0.18s;
}

.hero__lead {
  margin: 0 0 1.6rem;
  color: #efe0c8;
  font-size: clamp(1rem, 1.7vw, 1.16rem);
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.7);
  opacity: 0;
  transform: translateY(18px);
  animation: rise-in 0.55s ease-out forwards 0.24s;
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  opacity: 0;
  transform: translateY(18px);
  animation: rise-in 0.55s ease-out forwards 0.3s;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 50px;
  padding: 0.85rem 1.45rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.2s ease, background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

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

.btn--primary {
  background: linear-gradient(180deg, #ff3b3b, var(--blood) 55%, var(--blood-deep));
  color: #fff;
  box-shadow: 0 10px 24px rgba(212, 20, 26, 0.38), inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.btn--primary:hover {
  background: linear-gradient(180deg, #ff5555, #e61c22);
  color: #fff;
}

.btn--ghost {
  background: rgba(16, 6, 15, 0.4);
  border-color: var(--line);
  color: var(--bone);
}

.btn--ghost:hover {
  border-color: var(--gold);
  color: #fff;
  box-shadow: 0 0 0 1px rgba(224, 177, 90, 0.25);
}

.section {
  width: min(100% - 2rem, var(--max));
  margin: 0 auto;
  padding: 4.4rem 0;
}

.section__eyebrow {
  margin: 0 0 0.55rem;
  color: var(--gold);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.section__title {
  margin: 0 0 0.9rem;
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 4vw, 2.7rem);
  line-height: 1.12;
  font-weight: var(--font-display-weight);
  color: #fff6ea;
  text-shadow: 0 2px 0 rgba(90, 16, 24, 0.55);
}

.section__text {
  margin: 0 0 1rem;
  color: var(--bone-dim);
}

.section__text:last-child {
  margin-bottom: 0;
}

/* A section that carries a table or a figure after a text block does not need the full 4.4rem of
   air on top - the previous section already provided it, so this only trims the double gap. */
.section--flush {
  padding-top: 2.2rem;
}

/**
 * Long copy. The old rule capped every paragraph at 48rem, which on a wide screen left a half-empty
 * left-hand strip above full-width tables - the "half left-aligned, half full-width" look. From
 * 1080px up the copy now takes the whole column in two balanced tracks instead of one narrow stack.
 * Scoped to `.section > .prose` on purpose: prose inside `.two-col` is already a column and must
 * stay a single track.
 */
.prose {
  max-width: none;
}

@media (min-width: 1080px) {
  .section > .prose {
    columns: 2;
    column-gap: 3.5rem;
  }

  .section > .prose .section__text {
    break-inside: avoid;
  }
}

/**
 * Wide-screen rhythm. Every list-like block takes two tracks from 1080px up, so a checklist, a step
 * list or a card grid fills the 1360px column instead of running down the left edge with dead space
 * beside it - the same complaint as the 48rem paragraph cap.
 */

.specs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 2rem;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.28);
}

.spec {
  background: linear-gradient(180deg, rgba(58, 22, 56, 0.55), rgba(16, 6, 15, 0.92));
  padding: 1.15rem 1.1rem;
}

.spec dt {
  margin: 0;
  color: var(--gold);
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.spec dd {
  margin: 0.35rem 0 0;
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 2.5vw, 1.6rem);
  line-height: 1.15;
  color: #fff7ec;
}

.two-col {
  display: grid;
  gap: 2rem;
  align-items: center;
}

@media (min-width: 860px) {
  .specs {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .two-col {
    grid-template-columns: 1.05fr 0.95fr;
    gap: 3rem;
  }

  .two-col--reverse > :first-child {
    order: 2;
  }
}

.devices {
  width: 100%;
  filter: drop-shadow(0 24px 50px rgba(0, 0, 0, 0.45));
}

.checklist {
  margin: 1.25rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.7rem;
}

.checklist li {
  position: relative;
  padding: 0.85rem 1rem 0.85rem 2.6rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(28, 12, 26, 0.7);
  color: var(--bone-dim);
}

.checklist li::before {
  content: "🩸";
  position: absolute;
  left: 0.85rem;
  top: 0.8rem;
}

.feature-list {
  display: grid;
  gap: 1rem;
  margin: 2rem 0 0;
  padding: 0;
  list-style: none;
}

.feature-card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem 1.2rem 1.15rem;
  background:
    linear-gradient(160deg, rgba(212, 20, 26, 0.12), transparent 50%),
    rgba(28, 12, 26, 0.78);
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

.feature-card.is-visible {
  opacity: 1;
  transform: none;
}

.feature-card h3 {
  margin: 0 0 0.45rem;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: var(--font-display-weight);
}

.feature-card p {
  margin: 0;
  color: var(--bone-dim);
}

.bonus-grid {
  display: grid;
  gap: 1rem;
  margin-top: 2rem;
}

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

.bonus-card {
  position: relative;
  padding: 1.5rem 1.25rem 1.35rem;
  background:
    linear-gradient(165deg, rgba(212, 20, 26, 0.2), transparent 52%),
    linear-gradient(180deg, rgba(58, 22, 56, 0.7), rgba(16, 6, 15, 0.92));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: inset 0 1px 0 rgba(243, 212, 138, 0.12);
}

.bonus-card::after {
  content: "";
  position: absolute;
  left: 1.2rem;
  right: 1.2rem;
  top: 0;
  height: 4px;
  border-radius: 0 0 8px 8px;
  background: linear-gradient(90deg, var(--blood), var(--gold), var(--blood));
}

.bonus-card__tag {
  display: inline-block;
  margin-bottom: 0.7rem;
  color: var(--gold);
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.bonus-card h3 {
  margin: 0 0 0.55rem;
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: var(--font-display-weight);
}

.bonus-card p {
  margin: 0;
  color: var(--bone-dim);
  font-size: 0.95rem;
}

.table-wrap {
  margin-top: 1.5rem;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgba(16, 6, 15, 0.7);
}

table {
  width: 100%;
  border-collapse: collapse;
  min-width: 520px;
}

th,
td {
  padding: 0.85rem 1rem;
  text-align: left;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

th {
  background: rgba(212, 20, 26, 0.2);
  color: var(--gold-soft);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 800;
}

td {
  color: var(--bone-dim);
  font-size: 0.92rem;
}

tr:last-child td {
  border-bottom: 0;
}

.split-lists {
  display: grid;
  gap: 1rem;
  margin-top: 1.5rem;
}

@media (min-width: 720px) {
  .split-lists {
    grid-template-columns: 1fr 1fr;
  }
}

.taste-card {
  padding: 1.25rem 1.2rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
}

.taste-card--yes {
  background: linear-gradient(180deg, rgba(212, 20, 26, 0.16), rgba(16, 6, 15, 0.8));
}

.taste-card--no {
  background: linear-gradient(180deg, rgba(58, 22, 56, 0.35), rgba(16, 6, 15, 0.8));
}

.taste-card h3 {
  margin: 0 0 0.7rem;
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: var(--font-display-weight);
}

.taste-card ul {
  margin: 0;
  padding-left: 1.15rem;
  color: var(--bone-dim);
}

.faq {
  margin-top: 1.5rem;
}

/* Twelve answers stacked in one 1360px column read as a wall of text; two tracks fill the width and
   keep every answer at a comfortable measure. */
@media (min-width: 1080px) {
  .faq {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 3.5rem;
    align-content: start;
  }
}

.faq details {
  border-bottom: 1px solid var(--line);
  padding: 0.95rem 0;
}

.faq summary {
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: 1.12rem;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  align-items: center;
}

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

.faq summary::after {
  content: "+";
  color: var(--gold);
  font-family: var(--font-body);
  font-size: 1.2rem;
  font-weight: 800;
}

.faq details[open] summary::after {
  content: "-";
}

.faq p {
  margin: 0.7rem 0 0.2rem;
  color: var(--bone-dim);
}

.geo-grid {
  display: grid;
  gap: 1rem;
  margin-top: 1.75rem;
}

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

.geo-card {
  padding: 1.2rem;
  background: var(--mist);
  border-left: 3px solid var(--blood);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.geo-card h3 {
  margin: 0 0 0.4rem;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: var(--font-display-weight);
}

.geo-card p {
  margin: 0;
  color: var(--bone-dim);
  font-size: 0.92rem;
}

.demo-panel {
  margin-top: 2rem;
  padding: 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background:
    linear-gradient(180deg, rgba(212, 20, 26, 0.14), transparent),
    rgba(28, 12, 26, 0.85);
  display: grid;
  gap: 1rem;
}

@media (min-width: 800px) {
  .demo-panel {
    grid-template-columns: 1.2fr 0.8fr;
    align-items: center;
  }
}

.notice {
  margin-top: 1rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--bone-dim);
  font-size: 0.88rem;
  background: rgba(16, 6, 15, 0.45);
}

.site-footer {
  margin-top: 2rem;
  padding: 2.5rem clamp(1rem, 4vw, 2.5rem) 2rem;
  border-top: 1px solid var(--line);
  background:
    radial-gradient(600px 200px at 20% 0, rgba(212, 20, 26, 0.16), transparent 60%),
    #070306;
}

.footer-grid {
  width: min(100%, var(--max));
  margin: 0 auto;
  display: grid;
  gap: 1.5rem;
}

@media (min-width: 800px) {
  .footer-grid {
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  }
}

.site-footer h2,
.site-footer h3 {
  margin: 0 0 0.6rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: var(--font-display-weight);
}

.site-footer p,
.site-footer li {
  color: var(--bone-dim);
  font-size: 0.88rem;
}

.site-footer ul {
  margin: 0;
  padding-left: 1.1rem;
}

/* Footer links are small type: the bare text box is ~19px tall, under the 24px a thumb needs, so
   the hit box is padded out (Lighthouse's target-size check flags the bare box). */
.site-footer li a {
  display: inline-block;
  padding: 0.2rem 0;
}

.footer-meta {
  width: min(100%, var(--max));
  margin: 1.75rem auto 0;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
  color: var(--bone-dim);
  font-size: 0.78rem;
}

.footer-meta a {
  color: var(--bone-dim);
}

/* ==========================================================================
   LV-CSS-EXTRA - blocks the static build needs: header tools, alternating
   sections, tick lists and the stacked tables.
   ========================================================================== */
.header-tools {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-shrink: 0;
}

.btn--sm {
  min-height: 38px;
  padding: 0.45rem 0.95rem;
  font-size: 0.78rem;
}

/* The header's play button is the primary conversion and sits beside the brand, so it is a size up
   from the in-page `.btn--sm` links rather than one of them. */
.header-cta {
  min-height: 52px;
  padding: 0.9rem 1.6rem;
  font-size: 0.85rem;
  white-space: nowrap;
}

@media (max-width: 860px) {
  .header-tools {
    justify-content: center;
  }
}

/* Alternating bands behind the odd sections. */
.section--a {
  position: relative;
  width: 100%;
  max-width: none;
  padding-left: max(1rem, calc((100% - var(--max)) / 2));
  padding-right: max(1rem, calc((100% - var(--max)) / 2));
  background:
    radial-gradient(700px 340px at 88% 0, rgba(212, 20, 26, 0.14), transparent 62%),
    linear-gradient(180deg, rgba(9, 4, 8, 0.86), rgba(26, 10, 24, 0.62) 50%, rgba(9, 4, 8, 0.86));
  border-top: 1px solid rgba(224, 177, 90, 0.16);
  border-bottom: 1px solid rgba(224, 177, 90, 0.16);
}

.tick-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.55rem;
}

.tick-list li {
  position: relative;
  padding-left: 1.6rem;
  color: var(--bone-dim);
  font-size: 0.94rem;
}

.tick-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--gold);
  font-weight: 800;
}

/* Cards that fade in on scroll (js/main.js adds .is-visible). */
.bonus-card,
.geo-card,
.taste-card {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

.bonus-card.is-visible,
.geo-card.is-visible,
.taste-card.is-visible {
  opacity: 1;
  transform: none;
}

/* ---------------------------------------------------------------- tables */
table caption,
caption {
  padding: 0.85rem 1rem 0.2rem;
  color: var(--bone-dim);
  font-size: 0.8rem;
  text-align: left;
  caption-side: top;
}

.table--builds tbody th {
  color: var(--bone);
  font-weight: 800;
  font-size: 0.92rem;
  letter-spacing: 0;
  text-transform: none;
  background: transparent;
}

.table--builds td[data-calc] {
  font-variant-numeric: tabular-nums;
  color: var(--gold-soft);
  font-weight: 700;
}

.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

th.num {
  text-align: right;
}

/* On narrow screens every table turns into stacked label/value rows. */
@media (max-width: 640px) {
  table {
    min-width: 0;
  }

  .table--stack thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .table--stack tr {
    display: block;
    padding: 0.5rem 0.85rem;
    border-bottom: 1px solid var(--line);
  }

  .table--stack td,
  .table--stack th {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.25rem 0;
    border: 0;
    font-size: 0.9rem;
  }

  .table--stack td::before,
  .table--stack tbody th::before {
    content: attr(data-label);
    color: var(--gold);
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    flex: 0 0 42%;
  }

  .table--stack td[colspan]::before {
    content: none;
  }
}

@keyframes rise-in {
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes hero-drift {
  from {
    transform: scale(1.06) translate3d(0, 0, 0);
  }
  to {
    transform: scale(1.06) translate3d(-1.5%, -1%, 0);
  }
}

@keyframes bat-fly {
  0% {
    transform: translate3d(-10vw, 18vh, 0) rotate(-8deg);
  }
  50% {
    transform: translate3d(55vw, 8vh, 0) rotate(10deg);
  }
  100% {
    transform: translate3d(110vw, 22vh, 0) rotate(-6deg);
  }
}

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

  .hero__media,
  .hero__logo,
  .hero h1,
  .hero__lead,
  .cta-row,
  .feature-card,
  .bonus-card,
  .geo-card,
  .taste-card,
  .bat {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ------------------------------------------------------------------ deploy additions
   Score band, jump list, where-to-play panel, 18+ badge, consent bar, breadcrumb and the
   support-page typography. Everything reuses the existing palette variables. */

:focus-visible {
  outline: 2px solid var(--gold-soft);
  outline-offset: 3px;
}

.toc {
  width: min(100%, var(--max));
  margin: 0 auto;
  padding: 1.25rem clamp(1rem, 4vw, 2.5rem) 0;
}

.toc__title {
  margin: 0 0 0.55rem;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

.toc ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.toc a {
  display: inline-block;
  padding: 0.4rem 0.72rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(28, 12, 26, 0.6);
  color: var(--bone);
  font-size: 0.78rem;
  text-decoration: none;
}

.toc a:hover {
  border-color: var(--gold);
  color: var(--gold-soft);
}

.section--review {
  padding-top: 1.5rem;
}

.review {
  width: min(100%, var(--max));
  margin: 0 auto;
  display: grid;
  gap: 1.25rem;
  padding: 1.4rem clamp(1rem, 3vw, 1.8rem);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(58, 22, 56, 0.55), rgba(16, 6, 15, 0.75));
}

@media (min-width: 760px) {
  .review {
    grid-template-columns: 180px 1fr;
    align-items: start;
  }
}

.review__headline {
  text-align: center;
}

.review__value {
  margin: 0;
  font-family: var(--font-display);
  font-size: 2.9rem;
  line-height: 1;
  font-weight: var(--font-display-weight);
  color: var(--gold-soft);
}

.review__max {
  font-size: 1.05rem;
  color: var(--bone-dim);
}

.review__label {
  margin: 0.35rem 0 0;
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

.review__title {
  margin: 0 0 0.85rem;
  font-family: var(--font-display);
  font-size: 1.35rem;
}

.review__criteria {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.5rem;
}

.review__criteria li {
  display: grid;
  grid-template-columns: 1fr 110px 2.4rem;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.85rem;
  color: var(--bone-dim);
}

.review__bar {
  display: block;
  height: 6px;
  border-radius: 999px;
  background: rgba(246, 234, 212, 0.14);
  overflow: hidden;
}

.review__bar > span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--blood), var(--gold));
}

.review__score {
  text-align: right;
  color: var(--bone);
}

.review__meta {
  margin: 1rem 0 0;
  display: grid;
  gap: 0.5rem 1.4rem;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  font-size: 0.85rem;
}

.review__meta dt {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

.review__meta dd {
  margin: 0.12rem 0 0;
  color: var(--bone);
}

.review__meta a {
  color: var(--gold-soft);
}

.review__source {
  margin: 0.9rem 0 0;
  font-size: 0.8rem;
  color: var(--bone-dim);
}

.play__heading {
  margin: 0 0 0.6rem;
  font-family: var(--font-display);
  font-size: 1.1rem;
}

.play__panel {
  display: grid;
  gap: 0.9rem;
  align-content: start;
  padding: 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgba(16, 6, 15, 0.55);
}

.play__panel .table-wrap,
.play__panel .cta-row {
  margin: 0;
}

.play__panel caption {
  font-size: 0.78rem;
  color: var(--bone-dim);
}

.disclosure {
  margin: 0;
  padding-left: 0.7rem;
  border-left: 3px solid var(--gold);
  font-size: 0.78rem;
  color: var(--bone-dim);
}

.notice--age,
.footer__age {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
}

.age-badge {
  display: inline-grid;
  place-items: center;
  min-width: 2.4rem;
  padding: 0.15rem 0.45rem;
  border-radius: 8px;
  background: var(--blood);
  color: #fff;
  font-family: var(--font-display);
  font-weight: var(--font-display-weight);
  font-size: 0.85rem;
  letter-spacing: 0.04em;
}

.footer__age {
  width: min(100%, var(--max));
  margin: 1.4rem auto 0;
  font-size: 0.85rem;
  color: var(--bone-dim);
}

.footer__source {
  margin: 0.6rem 0 0;
}

.footer__source a {
  color: var(--gold-soft);
}

.nav-brand__text {
  font-family: var(--font-display);
  font-weight: var(--font-display-weight);
  font-size: 1.35rem;
  color: var(--bone);
}

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0 0 0.4rem;
  font-size: 0.8rem;
  color: var(--bone-dim);
}

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

.breadcrumb a:hover {
  text-decoration: underline;
}

.support .section {
  padding-top: 2rem;
}

/**
 * The guide overlays its header on the hero, which needs the header out of the flow. Support pages
 * and the series hub have no hero, so there the header keeps its place in the flow and reserves its
 * own height instead of the first block guessing a padding that works at every wrap point. It is
 * `sticky` rather than `static` so the menu is still pinned while the reader scrolls.
 */
.support .site-header {
  position: sticky;
  top: 0;
}

.support h2 {
  margin: 1.9rem 0 0.5rem;
  font-family: var(--font-display);
  font-size: 1.25rem;
}

.support h2:first-of-type {
  margin-top: 0.6rem;
}

.support .section__title + .section__text,
.support .section__text + .section__text {
  margin-top: 0.85rem;
}

.support .checklist {
  margin-top: 1rem;
}

.support .checklist a {
  color: var(--bone);
}

.consent {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 60;
  padding: 1rem clamp(1rem, 4vw, 2rem) calc(1rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: linear-gradient(0deg, rgba(9, 4, 7, 0.98), rgba(16, 6, 15, 0.95));
  backdrop-filter: blur(6px);
}

.consent__panel {
  width: min(100%, var(--max));
  margin: 0 auto;
  display: grid;
  gap: 0.6rem;
}

.consent__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.05rem;
}

.consent__text {
  margin: 0;
  font-size: 0.85rem;
  color: var(--bone-dim);
}

.consent__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
}

.consent__link {
  color: var(--gold-soft);
  font-size: 0.82rem;
}

.has-consent {
  padding-bottom: 9rem;
}

@media (prefers-reduced-motion: reduce) {
  .consent {
    backdrop-filter: none;
  }
}

/* ------------------------------------------------------------------ demo player + single operator
   The player is a facade: official Hacksaw artwork, one sponsored button, and - when the operator
   hands over a demo iframe URL - a click-to-load frame that replaces the poster in place. The
   operator panel replaces the old comparison table, because this site works with one partner. */

.player {
  margin-top: 1.6rem;
}

.player__stage {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #0b0409;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
}

.player__poster {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
}

/* Two tracks on a wide stage: the compliance badge and the fact line stay on the left while the
   sponsored button sits on the right, vertically centred against them. The old single-column grid
   left-aligned the badge and hint but let `.cta-row` keep its global `justify-content: center`, so the
   button floated in the middle of the strip with a dead gap beside the text. */
.player__overlay {
  position: absolute;
  inset: auto 0 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "badge cta"
    "hint cta";
  align-items: end;
  column-gap: clamp(1rem, 3vw, 2rem);
  row-gap: 0.55rem;
  padding: 1.35rem clamp(1rem, 3vw, 1.6rem);
  background: linear-gradient(180deg, transparent, rgba(9, 4, 8, 0.94) 58%);
}

.player__badge {
  grid-area: badge;
  justify-self: start;
  margin: 0;
  padding: 0.28rem 0.65rem;
  border: 1px solid var(--gold);
  border-radius: 999px;
  background: rgba(212, 20, 26, 0.82);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.player__hint {
  grid-area: hint;
  margin: 0;
  color: var(--bone-dim);
  font-size: 0.85rem;
}

/* The overlay row overrides the site-wide centred CTA rhythm: the button lives in the right-hand
   track, so it lines up with the badge and hint instead of floating free of them. */
.player__overlay .cta-row {
  grid-area: cta;
  align-self: center;
  justify-content: flex-end;
}

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

.player__facts {
  margin-top: 1.1rem;
}

.operator {
  padding: 1.15rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(58, 22, 56, 0.5), rgba(16, 6, 15, 0.72));
}

.operator__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: var(--font-display-weight);
  color: var(--bone);
}

.operator__tag {
  margin: 0.2rem 0 0.95rem;
  color: var(--gold-soft);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.operator__facts {
  display: grid;
  gap: 0.5rem;
  margin: 0 0 1rem;
}

.operator__row {
  display: grid;
  gap: 0.15rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid rgba(224, 177, 90, 0.14);
}

.operator__row:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.operator__row dt {
  color: var(--bone-dim);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.operator__row dd {
  margin: 0;
  color: var(--bone);
  font-size: 0.92rem;
}

/* A named but unlinked game: the hub cites Hacksaw's titles without sending readers away. */
.game-name {
  color: var(--bone);
  font-weight: 700;
}

/* An ordered step list on a spoke page (the HowTo the schema mirrors). */
.steps {
  display: grid;
  gap: 0.75rem;
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.steps li {
  position: relative;
  padding: 0.9rem 1.1rem 0.9rem 3.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgba(28, 12, 26, 0.62);
  color: var(--bone-dim);
  counter-increment: step;
}

.steps li::before {
  content: counter(step);
  position: absolute;
  left: 1rem;
  top: 0.85rem;
  width: 1.5rem;
  height: 1.5rem;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--blood);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 800;
}

.steps__title {
  display: block;
  margin-bottom: 0.15rem;
  color: var(--bone);
  font-weight: 800;
}

/* Spoke pages reuse the feature-card styling for their "related" cards. */
.feature-list a,
.feature-card h3 a {
  color: inherit;
  text-decoration-color: var(--gold);
}

/* The consent bar on a phone was taller than the hero CTA it covered. */
@media (max-width: 600px) {
  /* On a phone the poster is only ~240px tall, so an overlaid badge + hint + button used to bury
     the artwork. Below 600px the overlay moves under the image instead of on top of it, collapses to
     one track and keeps the whole stack - badge, hint and button - on the same left edge. */
  .player__overlay {
    position: static;
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "badge"
      "hint"
      "cta";
    padding: 1rem 0 0;
    background: none;
  }

  .player__overlay .cta-row {
    justify-content: flex-start;
  }

  .consent {
    padding: 0.75rem clamp(0.9rem, 4vw, 1.2rem) calc(0.75rem + env(safe-area-inset-bottom));
  }

  .consent__panel {
    gap: 0.45rem;
  }

  .consent__title {
    font-size: 0.95rem;
  }

  .consent__text {
    font-size: 0.78rem;
  }

  .consent__actions {
    gap: 0.45rem;
  }

  .has-consent {
    padding-bottom: 12.5rem;
  }

  /* The hero is exactly one viewport tall, so page padding cannot save its CTA from the fixed
     consent bar - the section itself has to make room. The reservation is unconditional: while it
     hung off `body.has-consent` the banner (added by js/consent.js after the first paint) pushed the
     whole hero copy up by ~100px the moment it appeared, which was the page's entire CLS score. The
     reserved height costs nothing when the banner is already answered - the hero copy just sits
     where a first-time visitor sees it - and the layout is now decided before the first paint. */
  .hero {
    padding-bottom: 12.5rem;
  }

  .nav-toggle {
    width: 42px;
    height: 42px;
  }
}

/* ------------------------------------------------------------------ navigation
   Kept at the end of the stylesheet on purpose: the base rules above (`.nav-links`
   align-items, the header flex row) describe the desktop header, and at equal specificity a
   media query written before them loses the cascade - which is exactly how the drawer ended up
   centred, half-width and full of wrapped desktop links on the first attempt. */

/**
 * Mobile navigation.
 *
 * The old rule simply wrapped the ten desktop links into three rows over the hero - the "desktop
 * menu on a phone" bug. Now the links, the language pills and the play button live inside a
 * `<details>` drawer: it opens natively (so the menu keeps working with JavaScript disabled),
 * js/main.js only adds "close on link, Escape and resize". From 861px up the drawer flattens with
 * `display: contents`, so the desktop flex row is byte-for-byte the layout it always was.
 */
.nav-drawer {
  display: contents;
}

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  place-items: center;
  list-style: none;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(16, 6, 15, 0.62);
  color: var(--bone);
  cursor: pointer;
}

.nav-toggle::-webkit-details-marker {
  display: none;
}

.nav-toggle::marker {
  content: "";
}

.nav-toggle:hover {
  border-color: var(--gold);
  color: var(--gold-soft);
}

.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  display: block;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.18s ease, background 0.18s ease;
}

.nav-toggle__bars {
  position: relative;
  margin: 0 auto;
}

.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: "";
  position: absolute;
  left: 0;
}

.nav-toggle__bars::before {
  top: -6px;
}

.nav-toggle__bars::after {
  top: 6px;
}

.nav-drawer[open] .nav-toggle__bars {
  background: transparent;
}

.nav-drawer[open] .nav-toggle__bars::before {
  transform: translateY(6px) rotate(45deg);
}

.nav-drawer[open] .nav-toggle__bars::after {
  transform: translateY(-6px) rotate(-45deg);
}

@media (max-width: 860px) {
  .site-header {
    flex-wrap: nowrap;
    gap: 0.75rem;
  }

  /* The drawer is a fixed panel over the top of the page and it lives inside the header's own
     stacking context, so raising the header alone would not have helped: the panel is a sibling of
     the toggle. The toggle - which is the close cross once the drawer is open - is lifted one step
     above the panel (31 over 30), and the header is lifted above the decorative atmosphere layer.
     Before this, the one control that closes the menu was the one control the menu painted over. */
  body.nav-open .site-header {
    z-index: 35;
  }

  /* ...and the page behind the panel stops scrolling (the panel is only as tall as its links, so
     without this a swipe below it dragged the article around under the open menu). */
  body.nav-open {
    overflow: hidden;
  }

  .nav-drawer {
    display: block;
    margin-left: auto;
  }

  .nav-toggle {
    display: grid;
    position: relative;
    z-index: 31;
  }

  .site-menu {
    position: fixed;
    inset: 0 0 auto;
    z-index: 30;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    max-height: 100svh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 5.4rem clamp(1rem, 5vw, 1.6rem) calc(1.5rem + env(safe-area-inset-bottom));
    border-bottom: 1px solid var(--line);
    /* Opaque, not 0.98: at that alpha the hero headline showed through the panel and read as
       ghosting behind the menu. */
    background: linear-gradient(180deg, #10060f, #1a0a18);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
  }

  .nav-links {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .nav-links a {
    display: block;
    padding: 0.85rem 0.5rem;
    font-size: 0.82rem;
    text-align: center;
    border-bottom: 1px solid rgba(224, 177, 90, 0.12);
  }

  .header-tools {
    flex-direction: column;
    align-items: stretch;
    gap: 0.9rem;
    padding-top: 0.4rem;
  }

  .header-cta {
    width: 100%;
    justify-content: center;
    min-height: 46px;
  }

  .lang-switch {
    justify-content: center;
  }

  /* The consent bar is fixed above everything, so the drawer has to reserve room for it or the
     last links and the play button end up underneath it. The height comes from js/consent.js
     (`--consent-reserve`, the bar measured on this very screen); the constant is the fallback for a
     browser that never ran the script. */
  body.has-consent .site-menu {
    padding-bottom: calc(var(--consent-reserve, 15rem) + 1rem + env(safe-area-inset-bottom));
  }
}

@media (min-width: 861px) {
  .nav-drawer > summary {
    display: none;
  }

  .nav-drawer,
  .nav-drawer > .site-menu {
    display: contents;
  }
}

/**
 * Chrome 131+ (and current Safari/Firefox) wrap a <details> body in a `::details-content` slot box,
 * which would otherwise keep the whole menu inside a zero-width block on desktop. Flattening the
 * slot in its own rule keeps the layout safe on engines that do not know the pseudo-element: there
 * the slot does not exist, so `display: contents` above is already enough.
 */
@media (min-width: 861px) {
  .nav-drawer::details-content {
    display: contents;
  }
}

/* ------------------------------------------------------------------ sticky play bar
   The "always one tap from the operator" layer. js/main.js clears the `hidden` attribute once the
   first in-page CTA has scrolled out of view, so the bar never doubles a button the reader can
   already see and never covers the hero CTA on arrival - and a page opened without JavaScript keeps
   exactly the CTAs it always had.

   One control on purpose: the bar is the sponsored play button and nothing else. The 18+ line and
   the affiliate disclosure live in the page's own footer blocks, where there is room to read them,
   instead of being shrunk into a strip on top of a button.

   Two shapes on purpose: a full-width bar in the thumb zone on a phone, a floating card on a
   desktop. A full-width strip across a 1440px screen reads as an ad banner, and this site sells
   trust before it sells a deposit.
   ---------------------------------------------------------------------------------------------- */
.sticky-cta {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 55;
  padding: 0.55rem clamp(0.75rem, 4vw, 1.4rem) calc(0.55rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: linear-gradient(0deg, rgba(9, 4, 7, 0.98), rgba(16, 6, 15, 0.94));
  backdrop-filter: blur(6px);
}

/* `hidden` in the markup is what keeps the bar out of the audit's tap-target scan before the
   reader has scrolled: a display:none element has no box to measure. */
.sticky-cta[hidden] {
  display: none;
}

.sticky-cta__panel {
  width: min(100%, var(--max));
  margin: 0 auto;
}

.sticky-cta__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
}

.sticky-cta__play {
  flex: 1 1 15rem;
}

/* The consent bar owns the bottom slot until the visitor answers it, and the open drawer covers the
   screen: the play bar stands down in both cases instead of stacking into a third of a phone. */
body.has-consent .sticky-cta,
body.nav-open .sticky-cta {
  display: none;
}

/* The bar is fixed, so the page has to reserve its height or the last line of the footer would sit
   under it forever. The values match the bar's shapes: one 50px button plus its padding on a phone,
   and the floating card (which also sits 1.4rem off the bottom edge) on a desktop.
   `:not(.has-consent)` keeps the consent bar's own (taller) padding in charge while that banner is
   up. */
body.has-sticky:not(.has-consent) {
  padding-bottom: 6rem;
}

/* In-flow CTA rows (every second section of a spoke page, and the closing row) reuse `.cta-row` for
   the button rhythm and only need air around them. */
.cta-row--inline {
  margin-top: 1.5rem;
}

.cta-row--final {
  margin-top: 1.75rem;
}

@media (max-width: 600px) {
  /* Phone: one sponsored button across the strip, so the bar stays a single thumb-reachable line
     and the label is never truncated to make room. */
  .sticky-cta__play {
    flex: 1 1 12rem;
  }
}

@media (min-width: 861px) {
  .sticky-cta {
    inset: auto auto 1.4rem 50%;
    width: min(46rem, calc(100% - 2.8rem));
    transform: translateX(-50%);
    padding: 0.7rem 0.95rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 18px 45px rgba(0, 0, 0, 0.5);
  }

  body.has-sticky:not(.has-consent) {
    padding-bottom: 7rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sticky-cta {
    backdrop-filter: none;
  }
}

@media print {
  .sticky-cta {
    display: none;
  }
}

/* ---------------------------------------------------------------- game frames */
.shot {
  margin: 1.5rem 0 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(180deg, rgba(28, 12, 26, 0.78), rgba(9, 4, 8, 0.92));
  box-shadow: 0 22px 50px rgba(0, 0, 0, 0.42);
}

.shot__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1280 / 690;
  object-fit: cover;
}

/* Six frames in two tracks on a tablet, three on a desktop: the grid fills the column instead of
   stacking tall screenshots down the page. */
.shot-grid {
  display: grid;
  gap: 1.25rem;
  margin-top: 2rem;
}

.shot-grid .shot {
  display: flex;
  flex-direction: column;
  margin: 0;
}

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

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

/* The hero frame sits above the fold, so it carries no card chrome: just the game, ringed in gold. */
.shot--hero {
  margin: 0;
  border-color: rgba(224, 177, 90, 0.45);
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.6);
}

@media (max-width: 979px) {
  .shot--hero {
    margin-top: 1.75rem;
  }
}

/* A figure dropped into a text section keeps a comfortable measure instead of the full 1360px. */
.section > .shot {
  max-width: 62rem;
}

/* ---------------------------------------------------------------- eyebrow marks */
.eyebrow__icon {
  display: inline-block;
  width: 1.15rem;
  height: 1.15rem;
  margin-right: 0.45rem;
  vertical-align: -0.22rem;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5));
}

/* ---------------------------------------------------------------- wide-screen rhythm */
/**
 * Two tracks for every list-like block from 1080px up. Written last on purpose: these selectors are
 * declared earlier in the file, so only a rule at the end of the cascade reliably wins the gap and
 * the track count at desktop widths.
 */
@media (min-width: 1080px) {
  .checklist,
  .tick-list,
  .steps,
  .feature-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .checklist,
  .steps {
    gap: 0.75rem 2.5rem;
  }

  .tick-list,
  .feature-list {
    gap: 1rem 2.5rem;
  }

  /* Lists inside a footer column or an already-two-track panel stay single-track. */
  .footer-grid .checklist,
  .footer-grid .tick-list,
  .two-col .checklist,
  .two-col .tick-list,
  .two-col .feature-list,
  .player .tick-list {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.7rem;
  }
}

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

/* ==========================================================================
   LV-CSS-STUDIO - the wide column, the one-row header and the game frames
   --------------------------------------------------------------------------
   Three things drove this block:

   1. the header only carried in-page anchors, so the rest of the cluster (demo, hub, the four
      support pages) was invisible from the menu;
   2. the reading column was capped at 48rem while the tables ran the full width, which read as a
      "half left-aligned, half full-width" page;
   3. the gameplay captures had no home.

   Everything here is additive and width-aware: the phone layout it inherits is untouched, the
   1080px/1240px tracks only fire on a desktop, and the one-row desktop menu is flattened away again
   below 861px where the drawer owns the same links.
   ========================================================================== */

/* ---------------------------------------------------------------- site menu: the page row */
@media (min-width: 861px) {
  /* One line: the brand, the site menu centred between the two edges, then the language pills and
     the play button. The three-column grid (`1fr auto 1fr`) gives both side tracks the same width,
     so the middle menu is centred on the page rather than merely left off the brand. Only the four
     content pages are in the menu now - the legal pages live in the footer - so it fits on the
     brand's row without the second header row it used to carry. */
  .site-header {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
  }

  .nav-brand {
    justify-self: start;
  }

  .site-nav--pages {
    justify-self: center;
  }

  .site-nav--pages .nav-links {
    flex-wrap: nowrap;
    gap: 0.35rem clamp(0.85rem, 1.8vw, 1.8rem);
    justify-content: center;
  }

  .site-nav--pages .nav-links a {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
    padding: 0.2rem 0;
    font-size: 0.8rem;
  }

  .header-tools {
    justify-self: end;
  }

  /* On a page that has a jump list, the `.toc` pills under the hero are the in-page navigation. */
  .site-nav--sections {
    display: none;
  }
}

@media (max-width: 860px) {
  /* Two labelled groups in the drawer: the site's pages, then this page's sections. The label is
     the nav's own aria-label, so the markup carries no extra decorative nodes. */
  .site-menu .site-nav + .site-nav {
    margin-top: 1.1rem;
  }

  .site-menu .site-nav::before {
    display: block;
    margin: 0 0 0.35rem;
    content: attr(aria-label);
    color: var(--gold);
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 0.16em;
    text-align: center;
    text-transform: uppercase;
  }
}

/* ---------------------------------------------------------------- hero: copy + live frame */
@media (min-width: 980px) {
  /* The hero is the one place a screenshot belongs above the fold: it answers "what is this" before
     a single line of copy is read, and the two columns fill the width instead of leaving the right
     half of a wide screen empty. */
  .hero__content {
    display: grid;
    grid-template-columns: 1.02fr 0.98fr;
    gap: 3.5rem;
    align-items: center;
    padding: 9rem 0 4rem;
  }
}

