/* ===========================================================================
   Dark arcade-brutalist.
   Flat colour and heavy type instead of gradients and glass — it reads
   premium, works in RTL, and stays cheap enough to hit the perf budget.
   =========================================================================== */

:root {
  --bg:        #0b0b0f;
  --surface:   #14141b;
  --surface-2: #1b1b24;
  --line:      #26262f;
  --text:      #f2f2f0;
  --muted:     #8a8a96;
  --dim:       #5c5c68;
  --accent:    #c6f135;
  --accent-d:  #a8ce22;
  --accent2:   #ff3d7f;

  --wrap: 1280px;
  --gap: 20px;
  --radius: 4px;

  --head-h: 60px;

  --ease: cubic-bezier(.2, .7, .3, 1);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  overflow-x: hidden;
}

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

/* Any author `display` rule beats the UA stylesheet's [hidden]{display:none},
   so an element with `hidden` would still render. This must come before any
   component sets its own display. */
[hidden] { display: none !important; }

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

h1, h2, h3 {
  margin: 0;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.05;
}

button { font: inherit; color: inherit; }

::selection { background: var(--accent); color: #000; }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 18px; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/*
   Skip link.

   NOT the classic `left: -9999px` off-canvas trick. That relies on overflow to
   the left being unscrollable — true in LTR, false in RTL, where the scroll
   origin is the right edge. On Arabic pages it produced 9,984px of horizontal
   scroll on every single page, measured at 390px wide.

   Clipping hides it without moving it anywhere, so it behaves identically in
   both directions and contributes no overflow at all.
*/
.skip {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip:focus {
  position: fixed;
  inset-inline-start: 0; top: 0;
  z-index: 200;
  width: auto; height: auto;
  margin: 0; padding: 10px 16px;
  clip-path: none;
  background: var(--accent); color: #000; font-weight: 700;
}

/* Grain — one tiny inline SVG, no image request */
.grain {
  position: fixed; inset: 0; z-index: 1; pointer-events: none; opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --- header -------------------------------------------------------------- */

.site-head {
  position: sticky; top: 0; z-index: 100;
  background: rgba(11, 11, 15, .93);
  backdrop-filter: blur(8px);
  border-bottom: 2px solid var(--line);
}

.site-head-inner {
  display: flex; align-items: center; gap: 18px;
  height: var(--head-h);
}

.brand { display: flex; align-items: center; gap: 9px; flex-shrink: 0; }

.brand-mark {
  display: grid; place-items: center;
  width: 28px; height: 28px;
  background: var(--accent); color: #000;
  border-radius: var(--radius);
  font-size: 12px;
}

.brand-name {
  font-weight: 900; font-size: 18px; letter-spacing: -0.04em; text-transform: uppercase;
}

.site-nav { display: flex; gap: 20px; font-weight: 600; font-size: 14px; }
.site-nav a { color: var(--muted); transition: color .15s var(--ease); }
.site-nav a:hover, .site-nav a:focus-visible { color: var(--accent); }

.site-search {
  margin-inline-start: auto;
  display: flex; align-items: center;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius);
  height: 34px; max-width: 260px; flex: 1;
}

.site-search input {
  flex: 1; min-width: 0;
  background: none; border: 0; outline: none;
  color: var(--text); padding: 0 12px; font-size: 13px;
}
.site-search input::placeholder { color: var(--dim); }

.site-search button {
  background: none; border: 0; cursor: pointer;
  color: var(--muted); padding: 0 11px; display: grid; place-items: center;
}
.site-search button:hover { color: var(--accent); }

.site-search:focus-within { border-color: var(--accent); }

.lang-switch {
  flex-shrink: 0;
  font-weight: 700; font-size: 13px;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 6px 11px;
}
.lang-switch:hover { color: var(--accent); border-color: var(--accent); }

.nav-toggle {
  display: none; background: none; border: 0; cursor: pointer;
  width: 34px; height: 34px; padding: 8px;
  flex-direction: column; justify-content: space-between;
}
.nav-toggle span { display: block; height: 2px; background: var(--text); }

/* Category strip is primary navigation, so it stays at the top on every page
   and marks the current category. */
.cat-strip {
  border-top: 1px solid var(--line);
  background: var(--bg);
}

.cat-strip-wrap { position: relative; display: flex; align-items: center; }

.cat-strip-inner {
  display: flex; gap: 7px;
  overflow-x: auto; overflow-y: hidden;
  padding: 8px 0;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
  scroll-behavior: smooth;
}
.cat-strip-inner::-webkit-scrollbar { width: 0; height: 0; display: none; }

.cat-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: 100px;
  color: var(--muted);
  font-size: 13px; font-weight: 600;
  white-space: nowrap;
  transition: color .15s var(--ease), border-color .15s var(--ease),
              background .15s var(--ease), transform .15s var(--ease);
}
.cat-chip .icon { opacity: .75; }

.cat-chip:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: translateY(-1px);
}
.cat-chip:hover .icon { opacity: 1; }

.cat-chip.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: #000;
}
.cat-chip.is-active .icon { opacity: 1; }

.strip-arrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 4;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--muted);
  cursor: pointer;
  box-shadow: 0 0 14px 8px var(--bg);
}
.strip-prev { inset-inline-start: -4px; }
.strip-next { inset-inline-end: -4px; }
.strip-arrow:hover { color: var(--accent); border-color: var(--accent); }
.strip-arrow[hidden] { display: none; }

[dir="rtl"] .strip-arrow svg { transform: scaleX(-1); }

@media (hover: none) {
  .strip-arrow { display: none !important; }
}

/* --- breadcrumbs --------------------------------------------------------- */

.crumbs {
  display: flex; flex-wrap: wrap; gap: 7px; align-items: center;
  padding-top: 16px; padding-bottom: 6px;
  font-size: 12.5px; color: var(--dim);
}
.crumbs a { color: var(--muted); }
.crumbs a:hover { color: var(--accent); }
.crumb-sep { color: var(--line); }

/* --- game page layout ---------------------------------------------------- */

.game-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 26px;
  padding-top: 8px;
  padding-bottom: 30px;
}

.game-title {
  font-size: clamp(26px, 4.4vw, 44px);
  margin-bottom: 16px;
  text-wrap: balance;
}

/* --- player -------------------------------------------------------------- */

/*
   The frame must respect each game's aspect ratio without ever dominating the
   viewport. Half the catalogue declares 800x600, which at full container width
   is ~690px tall and pushes everything below the fold; portrait games are worse
   still at ~1630px.

   So: cap the HEIGHT against the viewport, then derive the max WIDTH from that
   cap and the ratio. The ratio is always honoured, the height never runs away,
   and narrower results stay centred.
*/
.player-shell {
  --player-max-h: min(72vh, 700px);

  width: 100%;
  max-width: min(100%, calc(var(--player-max-h) * var(--aspect, 1.7778)));
  margin-inline: auto;
}

.player {
  position: relative;
  width: 100%;
  aspect-ratio: var(--aspect, 1.7778);
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  overflow: hidden;
  /* Reserved box: nothing here can shift once the frame loads */
}

.player-poster {
  position: absolute; inset: 0;
  display: grid; place-items: center;
}

.player-poster img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  filter: brightness(.42) saturate(.85);
}

.play-btn {
  position: relative; z-index: 2;
  display: inline-flex; align-items: center; gap: 11px;
  background: var(--accent); color: #000;
  border: 0; border-radius: var(--radius);
  padding: 15px 30px;
  font-weight: 800; font-size: 16px; letter-spacing: -0.01em;
  cursor: pointer;
  box-shadow: 5px 5px 0 rgba(0, 0, 0, .55);
  transition: transform .16s var(--ease), box-shadow .16s var(--ease);
}
.play-btn:hover, .play-btn:focus-visible {
  transform: translate(-2px, -2px);
  box-shadow: 7px 7px 0 rgba(0, 0, 0, .55);
}
.play-btn:active { transform: translate(1px, 1px); box-shadow: 3px 3px 0 rgba(0,0,0,.55); }

.play-icon { display: grid; place-items: center; }

.player-frame { position: absolute; inset: 0; }
.player-frame iframe { width: 100%; height: 100%; border: 0; display: block; }

.player-state {
  position: absolute; inset: 0; z-index: 3;
  display: grid; place-content: center; justify-items: center; gap: 10px;
  text-align: center; padding: 24px;
  background: var(--surface);
}

.state-icon {
  display: grid; place-items: center;
  width: 40px; height: 40px;
  background: var(--accent2); color: #fff;
  border-radius: var(--radius);
  font-weight: 900; font-size: 20px;
}

.state-title { font-size: 19px; }
.state-body { margin: 0; color: var(--muted); font-size: 14px; max-width: 42ch; }

.spinner {
  width: 30px; height: 30px;
  border: 3px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Toolbar sits BELOW the frame. It never overlaps the game's own controls,
   which almost always run along the bottom edge of the canvas. */
.player-toolbar {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 11px;
  background: var(--surface);
  border: 2px solid var(--line);
  border-top: 0;
  border-radius: 0 0 var(--radius) var(--radius);
}

.player-name {
  font-size: 12.5px; font-weight: 700; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}

.player-actions {
  margin-inline-start: auto;
  display: flex; gap: 6px; flex-shrink: 0;
}

.player-btn {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--muted);
  width: 34px; height: 34px;
  display: grid; place-items: center; cursor: pointer;
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.player-btn:hover, .player-btn:focus-visible { border-color: var(--accent); color: var(--accent); }

/* In fullscreen the shell is what expands, so the toolbar comes along and the
   exit control stays reachable. */
.player-shell:fullscreen {
  display: flex; flex-direction: column;
  width: 100vw; height: 100vh;
  background: #000;
}
.player-shell:fullscreen .player {
  flex: 1; aspect-ratio: auto; border: 0; border-radius: 0; min-height: 0;
}
.player-shell:fullscreen .player-toolbar { border: 0; border-top: 1px solid var(--line); }
.player-shell:fullscreen .rotate-hint { display: none; }

.rotate-hint {
  margin: 8px 0 0; text-align: center;
  font-size: 12.5px; color: var(--dim);
}

/* --- facts --------------------------------------------------------------- */

.facts {
  display: flex; flex-wrap: wrap; gap: 0;
  list-style: none; margin: 18px 0 0; padding: 0;
  border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden;
}

.facts li {
  flex: 1 1 140px;
  padding: 11px 15px;
  border-inline-end: 1px solid var(--line);
}
.facts li:last-child { border-inline-end: 0; }

.fact-key {
  display: block; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .09em; color: var(--dim); margin-bottom: 3px;
}
.fact-val { display: block; font-weight: 700; font-size: 14px; }
a.fact-val:hover { color: var(--accent); }

/* --- prose --------------------------------------------------------------- */

.prose { margin-top: 30px; max-width: 68ch; }
.prose h2 {
  font-size: 21px; margin-bottom: 11px;
  padding-inline-start: 11px;
  border-inline-start: 3px solid var(--accent);
}
.prose p { margin: 0 0 12px; color: #cfcfd4; }

.faq-item {
  border-bottom: 1px solid var(--line);
  padding: 12px 0;
}
.faq-item summary {
  cursor: pointer; font-weight: 700; font-size: 15px;
  list-style: none; display: flex; justify-content: space-between; gap: 12px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: '+'; color: var(--accent); font-weight: 800; }
.faq-item[open] summary::after { content: '−'; }
.faq-item p { margin: 9px 0 0; color: var(--muted); font-size: 14px; }

/* --- chips --------------------------------------------------------------- */

.chips-wrap { margin-top: 28px; }
.chips-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--dim); margin-bottom: 9px;
}
.chips { display: flex; flex-wrap: wrap; gap: 7px; }
.chip {
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 5px 11px; font-size: 12.5px; font-weight: 600; color: var(--muted);
  transition: all .15s var(--ease);
}
.chip:hover { border-color: var(--accent); color: var(--accent); }

/* --- sidebar ------------------------------------------------------------- */

.game-side { display: flex; flex-direction: column; gap: 20px; }

.side-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--dim); margin-bottom: 11px;
}

.side-list { display: flex; flex-direction: column; gap: 8px; }

.side-item {
  display: flex; align-items: center; gap: 11px;
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 7px; transition: all .15s var(--ease);
}
.side-item img { width: 62px; height: 46px; object-fit: cover; border-radius: 3px; }
.side-item span {
  font-size: 13px; font-weight: 600; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.side-item:hover { border-color: var(--accent); background: var(--surface); }

.ad-sticky { position: sticky; top: calc(var(--head-h) + 16px); }

/* --- cards & rails ------------------------------------------------------- */

.rails { padding-bottom: 40px; }

.rail { margin-top: 34px; }

.rail-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 14px; margin-bottom: 13px;
}

.rail-title {
  display: flex; align-items: center; gap: 9px;
  font-size: clamp(18px, 2.3vw, 25px);
  text-transform: uppercase;
}

.rail-ico {
  display: grid; place-items: center;
  width: 30px; height: 30px;
  flex-shrink: 0;
  background: var(--surface-2);
  border-radius: var(--radius);
  color: var(--accent);
}

.icon { display: block; }

/* Arrow lives in CSS, not in the PHP string — a literal → cannot flip for RTL */
.rail-more {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 700; color: var(--muted); white-space: nowrap;
}
.rail-more::after {
  content: '→';
  transition: transform .16s var(--ease);
}
.rail-more:hover { color: var(--accent); }
.rail-more:hover::after { transform: translateX(3px); }

[dir="rtl"] .rail-more::after { content: '←'; }
[dir="rtl"] .rail-more:hover::after { transform: translateX(-3px); }

/* Rails scroll horizontally rather than wrapping: a wrapping grid makes each
   section tall and pushes the other rails below the fold, and surfacing many
   games per screen is what drives games-per-session. Arrows restore the
   affordance the hidden scrollbar removes. */
.rail-wrap { position: relative; }

.rail-arrow {
  position: absolute;
  top: calc(50% - 18px);
  z-index: 5;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--text);
  cursor: pointer;
  opacity: 0;
  transition: opacity .16s var(--ease), border-color .16s var(--ease), color .16s var(--ease);
  box-shadow: 0 3px 14px rgba(0, 0, 0, .55);
}

.rail-prev { inset-inline-start: -6px; }
.rail-next { inset-inline-end: -6px; }

/* Visible on hover, and always visible once focused for keyboard users */
.rail-wrap:hover .rail-arrow,
.rail-arrow:focus-visible { opacity: 1; }

.rail-arrow:hover { border-color: var(--accent); color: var(--accent); }
.rail-arrow[hidden] { display: none; }

/* Direction glyphs must follow the writing direction */
[dir="rtl"] .rail-prev svg,
[dir="rtl"] .rail-next svg { transform: scaleX(-1); }

/* Touch devices have swipe, so arrows would only be clutter */
@media (hover: none) {
  .rail-arrow { display: none !important; }
}

/* Horizontal scrollers stay swipeable but never show a bar — a visible
   scrollbar under every rail is noise, and on Windows it also steals height
   from the tiles. */
/* Card size varies by how important the row is, so the page has a hierarchy
   instead of every row reading as equally significant. */
.rail-lg .rail-track { grid-auto-columns: minmax(234px, 1fr); }
.rail-md .rail-track { grid-auto-columns: minmax(196px, 1fr); }
.rail-sm .rail-track { grid-auto-columns: minmax(158px, 1fr); }

.rail-lg .card-title { font-size: 15px; }

.rail-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(196px, 1fr);
  gap: 14px;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 2px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* old Edge */

  /* Snap deliberately OFF here: on a snap container the browser cancels
     smooth programmatic scrolling, so the arrow buttons silently do nothing.
     Snap is only worth having for touch swiping, so it is scoped to that. */
  scroll-snap-type: none;
}
.rail-track::-webkit-scrollbar { width: 0; height: 0; display: none; }

@media (hover: none) {
  .rail-track { scroll-snap-type: x proximity; }
}

.card-game {
  scroll-snap-align: start;
  display: flex; flex-direction: column;
  height: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  transition: transform .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
}

.card-media {
  position: relative; display: block;
  aspect-ratio: 4 / 3;
  background: var(--surface-2);
}
.card-media img { width: 100%; height: 100%; object-fit: cover; }

/* A tile spanning extra grid rows is taller than its natural content, which
   otherwise leaves dead space inside the card. Let the artwork take the slack
   instead of the ratio holding it back. */
.card-span-2 .card-media,
.card-wide .card-media {
  aspect-ratio: auto;
  flex: 1 1 auto;
  min-height: 150px;
}

.card-flag {
  position: absolute; top: 6px; inset-inline-end: 6px;
  z-index: 2;
  background: var(--accent); color: #000;
  width: 20px; height: 20px; border-radius: 3px;
  display: grid; place-items: center; font-size: 11px; font-weight: 900;
}

/* Play affordance — makes the tile read as something you press rather than a
   link. Scales in on hover/focus, and is skipped under reduced motion. */
.card-play {
  position: absolute; inset: 0;
  z-index: 1;
  display: grid; place-items: center;
  background: rgba(11, 11, 15, .45);
  opacity: 0;
  transition: opacity .18s var(--ease);
}

.card-play svg {
  color: #000;
  background: var(--accent);
  border-radius: 50%;
  padding: 11px;
  width: 42px; height: 42px;
  transform: scale(.8);
  transition: transform .2s var(--ease);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .5);
}

.card-game:hover .card-play,
.card-game:focus-visible .card-play { opacity: 1; }

.card-game:hover .card-play svg,
.card-game:focus-visible .card-play svg { transform: scale(1); }

.card-media img { transition: transform .35s var(--ease); }
.card-game:hover .card-media img { transform: scale(1.06); }

.card-body {
  display: flex; align-items: center; gap: 7px;
  padding: 9px 10px;
}

.card-title {
  font-size: 14px; font-weight: 700; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; flex: 1;
}

.card-meta {
  flex-shrink: 0;
  font-size: 10px; font-weight: 800;
  background: var(--surface-2); color: var(--accent);
  border-radius: 3px; padding: 2px 5px;
}

.card-game:hover, .card-game:focus-visible {
  transform: translateY(-3px);
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), 4px 4px 0 rgba(198, 241, 53, .18);
}

/* --- homepage ------------------------------------------------------------ */

.hero { padding: 46px 18px 30px; }

.hero-title {
  font-size: clamp(46px, 12vw, 128px);
  line-height: .86;
  text-transform: uppercase;
  letter-spacing: -0.055em;
}
.hero-dot { color: var(--accent); }

.hero-sub {
  margin: 14px 0 0;
  color: var(--muted);
  font-size: clamp(14px, 1.7vw, 18px);
  max-width: 46ch;
}
.hero-sub strong { color: var(--accent); }

/* Broken grid: the first tile takes a 2x2 cell, the rest fill around it */
.hero-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: 14px;

  /* Spanning tiles leave holes when they do not fit the remaining columns;
     dense packing backfills those gaps with the smaller tiles that follow. */
  grid-auto-flow: dense;

  /* Explicit row height. Without it the 2x2 tile dictates the row size and
     every ordinary tile inherits ~190px of dead space below its artwork. */
  grid-auto-rows: 200px;
}

/* In the hero grid every tile fills its cell, whatever span it has */
.hero-grid .card-media {
  aspect-ratio: auto;
  flex: 1 1 auto;
  min-height: 0;
}

.card-span-2 { grid-column: span 2; grid-row: span 2; }
.card-span-2 .card-title { font-size: 19px; }
.card-span-2 .card-body { padding: 13px 14px; }

/* Wide but not tall — breaks the grid up without the 2x2 dominating */
.card-wide { grid-column: span 2; }
.card-wide .card-title { font-size: 16px; }

.cats { padding-bottom: 40px; }

/* Category tiles use a game thumbnail from inside the category as their
   artwork — a wall of text links reads as a sitemap, not a games site. */
.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(172px, 1fr));
  gap: 12px;
}

.cat-tile {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  transition: transform .16s var(--ease), border-color .16s var(--ease);
}

.cat-tile img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  filter: brightness(.42) saturate(.75);
  transition: filter .2s var(--ease), transform .3s var(--ease);
}

.cat-tile-body {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; justify-content: flex-end;
  gap: 2px;
  padding: 12px 13px;
  background: linear-gradient(to top, rgba(11, 11, 15, .82), transparent 65%);
}

.cat-icon {
  position: absolute; top: 10px; inset-inline-start: 11px;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  background: rgba(11, 11, 15, .72);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--accent);
  font-size: 13px;
}

.cat-name { font-weight: 800; font-size: 15px; letter-spacing: -0.01em; }
.cat-count { font-size: 11.5px; color: var(--muted); font-weight: 600; }

.cat-tile:hover { transform: translateY(-3px); border-color: var(--accent); }
.cat-tile:hover img { filter: brightness(.55) saturate(1); transform: scale(1.05); }
.cat-tile:hover .cat-name { color: var(--accent); }

/* --- ads ----------------------------------------------------------------- */

.ad {
  display: grid; place-items: center;
  margin: 16px 0;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.ad-inter, .promo.ad-inter { margin: 16px 0 0; }

/* --- walkthrough video ---------------------------------------------------- */

.walkthrough { margin: 26px 0; }

.walkthrough-title {
  font-size: 17px; font-weight: 800;
  letter-spacing: -.01em;
  margin-bottom: 12px;
}

/* Reserve the height the provider's player will take, so injecting it late
   cannot shift everything below it */
#gamemonetize-video {
  min-height: 480px;
  border-radius: var(--radius);
  overflow: hidden;
  background: #0e0e13;
  border: 1px solid var(--line);
}

/* --- house promos --------------------------------------------------------
   What fills an ad slot before a network is wired up. Same reserved box, so
   the layout we ship is the layout we get — but never an empty rectangle.
   ------------------------------------------------------------------------ */

.promo {
  display: block;
  margin: 16px 0;
  border-radius: var(--radius);
  overflow: hidden;
  position: relative;
  background:
    radial-gradient(120% 140% at 12% 0%, rgba(190, 255, 60, .13), transparent 58%),
    linear-gradient(150deg, #16161d 0%, #0e0e13 100%);
  border: 1px solid var(--line);
  isolation: isolate;
}

/* Faint diagonal hatch so the panel reads as designed surface, not a blank div */
.promo::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background-image: repeating-linear-gradient(
    -45deg, rgba(255, 255, 255, .028) 0 1px, transparent 1px 9px);
  pointer-events: none;
}

/* Promos inherit the slot's own classes (ad-sticky, ad-mobile, ad-inter), so
   the placement rules above apply to them unchanged. The device rules need
   the doubled selector: `.promo { display: block }` is declared after
   `.ad-mobile { display: none }` and would otherwise win on source order. */
.ad-mobile, .promo.ad-mobile { display: none; }

.promo-inner {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 16px;
  width: 100%; height: 100%;
  padding: 14px 16px;
  text-decoration: none; color: inherit;
}

.promo-media {
  flex: 0 0 auto;
  display: block; overflow: hidden;
  border-radius: 10px;
  background: #0a0a0e;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .45);
}

.promo-media img {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .4s cubic-bezier(.2, .7, .3, 1);
}

.promo-inner:hover .promo-media img { transform: scale(1.06); }

.promo-body {
  display: flex; flex-direction: column; gap: 5px;
  min-width: 0;
}

.promo-eyebrow {
  font-size: 10px; font-weight: 800;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--accent);
}

.promo-title {
  font-weight: 800; font-size: 17px; line-height: 1.22;
  color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

.promo-cta {
  align-self: start;
  margin-top: 3px;
  padding: 6px 13px;
  border-radius: 999px;
  background: var(--accent); color: #0a0a0e;
  font-size: 12px; font-weight: 800;
  letter-spacing: .02em;
  transition: transform .18s ease;
}

.promo-inner:hover .promo-cta { transform: translateY(-1px); }

/* Bar variant — leaderboards and anything wider than 2:1.
   The thumbnail scales to the slot height so a 90px bar and a 50px mobile bar
   both look deliberate, and the CTA sits at the far end instead of leaving a
   long empty run of background. */
.promo-bar .promo-inner { gap: 18px; }

/* Sized off the slot's own reserved height so the artwork can never grow the
   box past the space the ad would have taken */
.promo-bar .promo-media {
  height: calc(var(--slot-h, 90px) - 26px);
  width: auto; aspect-ratio: 4 / 3;
  max-width: 30%;
}

.promo-bar .promo-body {
  flex: 1 1 auto;
  flex-direction: row; align-items: center;
  gap: 16px;
}
.promo-bar .promo-eyebrow { flex: 0 0 auto; }
.promo-bar .promo-title   { flex: 1 1 auto; -webkit-line-clamp: 1; }
.promo-bar .promo-cta     { align-self: center; margin-top: 0; flex: 0 0 auto; }

/* Poster variant — sidebars, squares, in-content rectangles.
   The card is centred and capped: an in-content slot is only ~336px wide as an
   ad, but its container is the full column, and a full-width promo would be
   several hundred pixels taller than the space the ad reserved. */
.promo-poster .promo-inner {
  flex-direction: column; align-items: stretch;
  justify-content: flex-start; gap: 12px;
  padding: 12px;
  max-width: 340px; margin-inline: auto;
}
.promo-poster .promo-media {
  width: auto; aspect-ratio: 4 / 3;
  height: calc(var(--slot-h, 250px) - 118px);
  max-width: 100%; align-self: center;
}
.promo-poster .promo-body  { flex: 0 0 auto; }
.promo-poster .promo-cta   { align-self: stretch; text-align: center; }

/* Stacked variant — tall slots (a 600px sidebar) carry several cards so the
   box is filled rather than one small promo floating in dead space */
.promo-stack { display: flex; flex-direction: column; padding: 12px; gap: 10px; }
.promo-stack .promo-inner { max-width: none; margin-inline: 0; }

.promo-stack-head { position: relative; z-index: 1; }

.promo-stack .promo-inner {
  flex: 1 1 0; min-height: 0;
  flex-direction: row; align-items: center; gap: 12px;
  padding: 8px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .028);
  transition: background .2s ease;
}
.promo-stack .promo-inner:hover { background: rgba(255, 255, 255, .06); }
/* Sized on width, not height: the sidebar is narrow, so width is the binding
   constraint and driving off height would squash the 4:3 artwork */
.promo-stack .promo-media {
  width: 40%; height: auto; aspect-ratio: 4 / 3;
  flex: 0 0 auto; align-self: center;
}
/* flex:1 + min-width:0 is what lets the clamp actually clip; without it the
   title sets the card's width and runs past the edge */
.promo-stack .promo-body  { flex: 1 1 auto; min-width: 0; }
.promo-stack .promo-title { font-size: 14px; overflow-wrap: anywhere; }
.promo-stack .promo-cta {
  align-self: start; text-align: start;
  padding: 4px 10px; font-size: 11px;
}

/* Brand fallback — no catalogue yet, so no game to promote */
.promo-brand { justify-content: center; text-align: center; }
.promo-brand .promo-body { align-items: center; }
.promo-brand .promo-title { font-size: 20px; }

@media (prefers-reduced-motion: reduce) {
  .promo-media img, .promo-cta { transition: none; }
  .promo-inner:hover .promo-media img { transform: none; }
}

/* --- interstitial -------------------------------------------------------- */

.interstitial {
  position: fixed; inset: 0; z-index: 150;
  display: grid; place-items: center;
  background: rgba(6, 6, 9, .88);
  padding: 20px;
}

.interstitial-panel {
  position: relative;
  width: 100%; max-width: 560px;
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
  animation: pop .22s var(--ease);
}
@keyframes pop { from { transform: scale(.96); opacity: 0; } }

.interstitial-close {
  position: absolute; top: 8px; inset-inline-end: 10px;
  background: none; border: 0; cursor: pointer;
  color: var(--muted); font-size: 26px; line-height: 1;
}
.interstitial-close:hover { color: var(--accent); }

.interstitial-kicker { margin: 0 0 3px; font-size: 12.5px; color: var(--muted); }
.interstitial-title { font-size: 24px; text-transform: uppercase; margin-bottom: 16px; }

.interstitial-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 11px;
}

.btn-ghost {
  margin-top: 16px; width: 100%;
  background: none; border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--muted);
  padding: 10px; font-weight: 700; cursor: pointer;
}
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }

/* --- listing pages ------------------------------------------------------- */

.list-head { padding: 22px 18px 16px; }

.list-count { margin: 8px 0 0; color: var(--muted); font-size: 14px; }
.list-count strong { color: var(--accent); }
.list-page { color: var(--dim); }

.list-intro {
  margin-top: 12px;
  max-width: 68ch;
  color: #cfcfd4;
  font-size: 14.5px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 13px;
}

/* --- pagination ---------------------------------------------------------- */

.pager {
  display: flex; flex-wrap: wrap; gap: 6px;
  align-items: center; justify-content: center;
  padding: 30px 18px 10px;
}

.pager-num, .pager-btn {
  min-width: 36px; height: 36px;
  display: grid; place-items: center;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 13px; font-weight: 700;
  color: var(--muted);
  transition: all .15s var(--ease);
}
.pager-num:hover, .pager-btn:hover { border-color: var(--accent); color: var(--accent); }

.pager-num.is-current {
  background: var(--accent); border-color: var(--accent); color: #000;
}

.pager-gap { color: var(--dim); padding: 0 4px; }

/* --- big search ---------------------------------------------------------- */

.search-big {
  display: flex; gap: 8px;
  margin-bottom: 8px;
}

.search-big input {
  flex: 1; min-width: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text);
  padding: 12px 15px;
  font-size: 15px;
  outline: none;
}
.search-big input:focus { border-color: var(--accent); }
.search-big input::placeholder { color: var(--dim); }

.search-big button {
  background: var(--accent); border: 0;
  border-radius: var(--radius);
  color: #000; font-weight: 800;
  padding: 0 22px; cursor: pointer;
  white-space: nowrap;
}
.search-big button:hover { background: var(--accent-d); }

/* --- static pages -------------------------------------------------------- */

.static { padding: 22px 18px 40px; }
.static-body { margin-top: 18px; max-width: 70ch; }
.static-body h2 { font-size: 20px; margin: 24px 0 10px; }
.static-body ul, .static-body ol { color: #cfcfd4; padding-inline-start: 22px; }
.static-body li { margin-bottom: 6px; }
.static-body a { color: var(--accent); text-decoration: underline; }

/* --- notice / 404 -------------------------------------------------------- */

.notice { padding: 50px 0 10px; text-align: center; }
.page-title { font-size: clamp(28px, 5vw, 48px); text-transform: uppercase; }
.notice-body { color: var(--muted); margin-top: 10px; }

/* --- footer -------------------------------------------------------------- */

.site-foot {
  border-top: 2px solid var(--line);
  margin-top: 30px; padding: 34px 0 40px;
  background: var(--surface);
}
.foot-top { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.foot-tag { margin: 0; color: var(--muted); font-size: 13.5px; }
.foot-nav { display: flex; flex-wrap: wrap; gap: 18px; margin-top: 18px; font-size: 13.5px; }
.foot-nav a { color: var(--muted); }
.foot-nav a:hover { color: var(--accent); }
.foot-legal { margin: 20px 0 0; color: var(--dim); font-size: 12.5px; }

/* --- focus --------------------------------------------------------------- */

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

/* --- mobile tab bar ------------------------------------------------------ */
/* Hidden on desktop; on a phone it gives thumb-reachable navigation instead of
   a header the user has to scroll back up to reach. */

.tabbar { display: none; }

/* --- responsive ---------------------------------------------------------- */

@media (max-width: 1024px) {
  .game-layout { grid-template-columns: minmax(0, 1fr); }
  .game-side { display: none; }
  .hero-grid { grid-auto-rows: 176px; }
}

@media (max-width: 760px) {

  /* Width is the binding constraint on a phone, so allow more height — but
     never a full screen of frame with nothing else visible. */
  .player-shell { --player-max-h: min(62vh, 520px); }

  .site-nav { display: none; }
  .nav-toggle { display: flex; }

  .site-head-inner { flex-wrap: wrap; height: auto; padding-top: 10px; gap: 10px; }

  /*
     The search box carries `margin-inline-start: auto` on desktop, and that is
     what pushes everything after it to the far edge. On mobile it drops to its
     own full-width row, taking the auto margin with it — which left the
     language switch and the menu button floating mid-header with dead space
     beside them.

     Moving the auto margin onto the language switch restores the behaviour:
     it and the menu button after it sit flush against the end of the row, in
     both text directions.
  */
  .site-search { max-width: none; order: 3; width: 100%; margin: 0 0 10px; height: 40px; }

  .lang-switch {
    padding: 8px 12px;
    margin-inline-start: auto;
  }

  /* Last item in the row, so it sits hard against the edge */
  .nav-toggle { margin-inline-end: 0; }

  .site-head.is-open .site-nav {
    display: flex; order: 4; width: 100%;
    flex-direction: column; gap: 0;
    border-top: 1px solid var(--line);
  }
  .site-head.is-open .site-nav a { padding: 13px 0; border-bottom: 1px solid var(--line); }

  .ad-mobile { display: grid; }
  .promo.ad-mobile { display: block; }
  .ad-desktop, .promo.ad-desktop { display: none; }

  /* Tap targets stay comfortable */
  .cat-chip { padding: 9px 14px; font-size: 13.5px; }

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

  /* Two full tiles plus a hint of the third, so it reads as scrollable */
  .rail-track,
  .rail-lg .rail-track,
  .rail-md .rail-track { grid-auto-columns: minmax(43vw, 1fr); }

  .hero-grid {
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: 150px;
  }
  /* A 2x2 tile on a 2-column grid would be the entire viewport */
  .card-span-2 { grid-column: span 2; grid-row: span 1; }
  .card-span-2 .card-title { font-size: 16px; }
  .card-wide { grid-column: span 2; }

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

  .rail { margin-top: 26px; }
  .hero { padding: 30px 18px 22px; }

  /* Tab bar takes over navigation */
  .tabbar {
    position: fixed; inset-inline: 0; bottom: 0; z-index: 120;
    display: grid; grid-template-columns: repeat(4, 1fr);
    background: rgba(20, 20, 27, .97);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom);
  }

  .tab {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    padding: 9px 4px 8px;
    color: var(--muted);
    font-size: 10.5px; font-weight: 600;
    min-height: 52px;
  }
  .tab .icon { opacity: .8; }
  .tab:active { color: var(--accent); }
  .tab:active .icon { opacity: 1; }

  /* Room so the tab bar never covers the last row */
  body { padding-bottom: 58px; }
  .site-foot { margin-bottom: 0; }

  /* --- touch sizing ------------------------------------------------------
     Everything below was measured in a 390px viewport, not guessed.
     ---------------------------------------------------------------------- */

  /*
     iOS zooms the whole page when you focus an input whose font-size is under
     16px, and it does not zoom back out afterwards. The search box was 13px
     and 15px tall — so tapping search on an iPhone left the visitor stranded
     on a zoomed page with no obvious way back. This is the single worst
     mobile bug on the site.
  */
  .site-search { height: 44px; max-width: none; }

  .site-search input {
    font-size: 16px;          /* must stay >= 16px, see above */
    padding: 0 14px;
    min-height: 44px;
  }

  .site-search button {
    min-width: 44px; min-height: 44px;
    padding: 0 12px;
  }

  /* 44px is the smallest reliably tappable target */
  .nav-toggle { width: 44px; height: 44px; padding: 11px; }

  .lang-switch { min-height: 44px; display: inline-flex; align-items: center; }

  .brand { min-height: 44px; display: inline-flex; align-items: center; }

  /* "All games ->" was 19px tall — a link people genuinely try to tap */
  .rail-more {
    min-height: 40px;
    padding-inline: 4px;
    font-size: 13px;
  }

  .player-btn { min-width: 42px; min-height: 42px; }

  .fact-val, .fact-key { min-height: 24px; }

  .chip, .cat-chip { min-height: 40px; display: inline-flex; align-items: center; }

  /* Text that was too small to read comfortably at arm's length */
  .cat-count { font-size: 12.5px; }
  .promo-eyebrow { font-size: 11px; }
  .card-meta { font-size: 12px; }

  /*
     Rail and strip arrows are pointer affordances. On touch the row is swiped
     directly, so they only take up room and invite mis-taps. Already hidden
     under `(hover: none)`; hidden by width too, because a touch laptop matches
     hover and would otherwise keep 28px buttons nobody can hit accurately.
  */
  .rail-arrow, .strip-arrow { display: none !important; }

  /* Footer links were 21px tall in a six-link row — easy to hit the wrong one */
  .foot-nav {
    gap: 4px 18px;
  }
  .foot-nav a {
    min-height: 40px;
    display: inline-flex; align-items: center;
  }

  /* Breadcrumbs are a real navigation path back out of a game page */
  .crumbs { gap: 6px 8px; }
  .crumbs a,
  .crumbs span[aria-current] {
    min-height: 36px;
    display: inline-flex; align-items: center;
  }

  .facts a.fact-val { min-height: 36px; display: inline-flex; align-items: center; }

  /* Pagination is a row of adjacent small squares — the worst case for
     mis-taps, since every neighbour is a different page */
  .pager-btn, .pager-num {
    min-width: 44px; min-height: 44px;
  }

  /* --- house promo, bar variant -----------------------------------------
     Measured on a 335px bar: thumbnail 32px + "FEATURED" 71px + CTA 82px +
     gaps left the title 66px, so "3D Police Car Parking" rendered as "3D…".
     A promo whose title is unreadable is worse than an empty box — it is the
     same space, spent telling the visitor nothing.

     The eyebrow is the part with no job on a phone: the CTA already says this
     is something to play, and the title is what decides whether they want to.
     ---------------------------------------------------------------------- */

  .promo-bar .promo-eyebrow { display: none; }

  .promo-bar .promo-inner { gap: 10px; padding: 8px 10px; }

  .promo-bar .promo-body { gap: 10px; min-width: 0; }

  .promo-bar .promo-title {
    flex: 1 1 auto; min-width: 0;
    font-size: 14px;
    -webkit-line-clamp: 2;
  }

  .promo-bar .promo-cta {
    flex: 0 0 auto;
    padding: 6px 11px; font-size: 11.5px;
  }

  /* A 50px mobile banner slot leaves ~24px of artwork, which reads as a
     smudge. Below that height the thumbnail is not worth its width. */
  .promo-bar[style*="--slot-h:50px"] .promo-media { display: none; }
}

@media (max-width: 400px) {
  .rail-track,
  .rail-lg .rail-track,
  .rail-md .rail-track { grid-auto-columns: minmax(46vw, 1fr); }

  .hero-grid { grid-auto-rows: 132px; }
  .interstitial-panel { padding: 20px 16px; }
  .hero-title { font-size: clamp(38px, 15vw, 64px); }
}

/* --- reduced motion ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .card-game:hover { transform: none; }
  .play-btn:hover { transform: none; }
}
