/* ============================================================
   spielkunst — identity "SIGNAL"
   ------------------------------------------------------------
   One system, three ingredients:
     ink      near-black stage with warm paper type
     signal   a single acid-lime action colour
     coin     warm amber, used only for the daily grid
   Everything else is a hairline. No scanlines, no rainbow chrome.

   Derived from extracted values (designeer.xyz dark surface + easing
   vocabulary), re-cut for an arcade. Values only, no borrowed assets.
   ============================================================ */

:root {
  color-scheme: dark;

  /* -- stage ------------------------------------------------- */
  --ink: #08090a;
  --ink-2: #0b0d0f;
  --panel: #131518;
  --panel-2: #191c20;
  --panel-3: #22262b;
  --sunk: #0e1013;

  /* -- hairlines --------------------------------------------- */
  --hair: #ffffff12;
  --hair-2: #ffffff24;
  --hair-3: #ffffff38;

  /* -- ink on stage (warm paper, never pure white) ----------- */
  --paper: #f6f3eb;
  --paper-2: #b6b2a8;
  --paper-3: #8a867d;

  /* -- signal ------------------------------------------------ */
  --signal: #c9f94b;
  --signal-2: #dcff7a;
  --signal-ink: #0b1000;
  --signal-text: #c9f94b;
  --signal-soft: #c9f94b1f;
  --signal-line: #c9f94b4d;

  /* -- coin (daily puzzle only) ------------------------------ */
  --coin: #ffc46b;
  --coin-ink: #17120a;
  --coin-text: var(--coin);
  --coin-soft: #ffc46b1f;

  /* -- category hues ----------------------------------------- */
  --c-word: #ff7fb8;
  --c-puzzle: #ffc46b;
  --c-arcade: #6fe3ff;
  --c-brain: #8be8b8;
  --c-strategy: #ff9e7a;
  --c-sandbox: #b8a6ff;

  /* -- shape ------------------------------------------------- */
  --r-xs: 6px;
  --r-sm: 9px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-pill: 999px;

  /* -- elevation: hairline first, then a soft close shadow --- */
  --lift: inset 0 0 0 1px var(--hair), 0 1px 2px #00000080, 0 10px 26px -18px #000000cc;
  --lift-hi: inset 0 0 0 1px var(--hair-2), 0 2px 4px #00000099, 0 22px 44px -24px #000000e6;
  --lift-signal: inset 0 0 0 1px var(--signal-line), 0 14px 40px -22px #c9f94b66;

  /* -- motion (exact designeer vocabulary) ------------------- */
  --e-out: cubic-bezier(0.23, 1, 0.32, 1);
  --e-spring: cubic-bezier(0.3, 1.12, 0.4, 1);
  --e-io: cubic-bezier(0.4, 0, 0.2, 1);
  --e-morph: cubic-bezier(0.33, 0.55, 0.2, 1);
  --t-fast: 140ms;
  --t-mid: 240ms;
  --t-slow: 520ms;

  /* -- type -------------------------------------------------- */
  --f-display: 'Bricolage Grotesque', 'Outfit', ui-sans-serif, system-ui, sans-serif;
  --f-body: 'Outfit', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --f-mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --t-label: 11px;
  --t-sm: 13px;
  --t-base: 15px;
  --t-md: 17px;
  --t-lg: clamp(20px, 2.1vw, 25px);
  --t-xl: clamp(26px, 3.2vw, 36px);
  --t-hero: clamp(38px, 5.2vw, 66px);

  /* -- metrics ----------------------------------------------- */
  --tap: 44px;
  --wrap: 1180px;
  --gutter: clamp(16px, 4vw, 32px);
  --head-h: 64px;
}

/* ------------------------------------------------------------
   Themes
   A theme only swaps tokens: stage, panels, ink on stage, the signal
   colour and the coin. Shape, spacing, motion and type never change, so
   every theme is the same product in a different coat — and every one of
   them is contrast-checked (AA on body and meta text).
   ------------------------------------------------------------ */

/* 1 · Signal — the default. Near-black stage, acid lime. */
html[data-theme='signal'] {
  color-scheme: dark;
}

/* 2 · Lights on — paper stage, ink type. For daylight and projectors. */
html[data-theme='lights'] {
  color-scheme: light;
  --ink: #f7f4ec;
  --ink-2: #fffdf7;
  --panel: #fffefb;
  --panel-2: #f2eee3;
  --panel-3: #e7e2d5;
  --sunk: #efeadc;
  --hair: #14160f1a;
  --hair-2: #14160f2e;
  --hair-3: #14160f45;
  --paper: #14160f;
  --paper-2: #4e5245;
  --paper-3: #5f6355;
  --signal: #c2f23f;
  --signal-2: #a8d92a;
  --signal-ink: #101700;
  --signal-text: #4c6b00;
  --signal-soft: #a8d92a24;
  --signal-line: #5f7a1f80;
  --coin: #ffc46b;
  --coin-ink: #241603;
  --coin-text: #8a4b00;
  --coin-soft: #ffc46b29;
  --lift: inset 0 0 0 1px var(--hair), 0 1px 2px #14160f0f, 0 10px 26px -20px #14160f40;
  --lift-hi: inset 0 0 0 1px var(--hair-2), 0 2px 4px #14160f14, 0 22px 44px -26px #14160f38;
}

/* 3 · Coin-op — warm cabinet, amber signal, ashtray beige type. */
html[data-theme='coinop'] {
  color-scheme: dark;
  --ink: #0d0907;
  --ink-2: #120c08;
  --panel: #1a120c;
  --panel-2: #22170f;
  --panel-3: #2e2016;
  --sunk: #150e09;
  --paper: #fdf2e0;
  --paper-2: #c9b59a;
  --paper-3: #a08a70;
  --signal: #ffb648;
  --signal-2: #ffc86b;
  --signal-ink: #1a0f00;
  --signal-text: #ffc46b;
  --signal-soft: #ffb64824;
  --signal-line: #ffb64866;
  --coin: #ff8f4a;
  --coin-soft: #ff8f4a1f;
}

/* 4 · Ice — cool blue stage, cyan signal. */
html[data-theme='ice'] {
  color-scheme: dark;
  --ink: #050b12;
  --ink-2: #08111a;
  --panel: #0c1620;
  --panel-2: #101d29;
  --panel-3: #172836;
  --sunk: #081019;
  --paper: #eaf6ff;
  --paper-2: #a6c0d4;
  --paper-3: #8aa4b8;
  --signal: #4fe3ff;
  --signal-2: #7deeff;
  --signal-ink: #001318;
  --signal-text: #6fe3ff;
  --signal-soft: #4fe3ff24;
  --signal-line: #4fe3ff66;
  --coin: #ffd166;
  --coin-soft: #ffd1661f;
}

/* 5 · DMG — the four greens of a 1989 handheld. */
html[data-theme='dmg'] {
  color-scheme: dark;
  --ink: #0b1410;
  --ink-2: #0e1a14;
  --panel: #13221a;
  --panel-2: #192c22;
  --panel-3: #213a2c;
  --sunk: #0f1b15;
  --paper: #d7ecc0;
  --paper-2: #9dbb84;
  --paper-3: #86a370;
  --signal: #9bbc0f;
  --signal-2: #b6d526;
  --signal-ink: #0b1400;
  --signal-text: #c3dc4a;
  --signal-soft: #9bbc0f24;
  --signal-line: #9bbc0f66;
  --coin: #e0c341;
  --coin-soft: #e0c3411f;
}

/* 6 · Vapor — violet stage, hot pink signal, mint coin. */
html[data-theme='vapor'] {
  color-scheme: dark;
  --ink: #0d0716;
  --ink-2: #120a1e;
  --panel: #1a0f2a;
  --panel-2: #221437;
  --panel-3: #2d1b47;
  --sunk: #120a20;
  --paper: #fbeaff;
  --paper-2: #c3a8d6;
  --paper-3: #ab93bf;
  --signal: #ff6ec7;
  --signal-2: #ff8fd4;
  --signal-ink: #1a0010;
  --signal-text: #ff9ad8;
  --signal-soft: #ff6ec724;
  --signal-line: #ff6ec766;
  --coin: #7df9ff;
  --coin-soft: #7df9ff1f;
}

/* 7 · Pixel — a 16-bit cartridge: 8 colours, hard 2px edges, zero radius,
   no soft shadow anywhere. Shape is a token in this system, so the whole coat
   is a token swap plus the pixel type face. */
html[data-theme='pixel'] {
  color-scheme: dark;
  --ink: #14121f;
  --ink-2: #191730;
  --panel: #221f3d;
  --panel-2: #2b2750;
  --panel-3: #353066;
  --sunk: #0f0d1a;
  --hair: #ffffff1f;
  --hair-2: #ffffff33;
  --hair-3: #ffffff5c;
  --paper: #f4f1e8;
  --paper-2: #c3bede;
  --paper-3: #a49ec4;
  --signal: #ffcc4d;
  --signal-2: #ffdd80;
  --signal-ink: #1a1400;
  --signal-text: #ffd980;
  --signal-soft: #ffcc4d26;
  --signal-line: #ffcc4d73;
  --coin: #6fd3ff;
  --coin-ink: #041820;
  --coin-text: #9de5ff;
  --coin-soft: #6fd3ff26;
  --c-word: #ff8fb4;
  --c-puzzle: #ffcc4d;
  --c-arcade: #6fd3ff;
  --c-brain: #8be08b;
  --c-strategy: #ff9e6b;
  --c-sandbox: #b9a4ff;
  /* shape: nothing round, nothing soft */
  --r-xs: 0px;
  --r-sm: 0px;
  --r-md: 0px;
  --r-lg: 0px;
  --r-xl: 0px;
  --r-pill: 0px;
  --lift: 0 0 0 2px var(--hair-3), 4px 4px 0 0 #000;
  --lift-hi: 0 0 0 2px var(--signal-line), 6px 6px 0 0 #000;
  --lift-signal: 0 0 0 2px var(--signal), 4px 4px 0 0 #000;
  /* type: pixel display, pixel text, pixel numerals */
  --f-display: 'Silkscreen', 'Pixelify Sans', ui-monospace, monospace;
  --f-body: 'Pixelify Sans', ui-monospace, monospace;
  --f-mono: 'Silkscreen', ui-monospace, monospace;
  --t-label: 12px;
  --t-sm: 14px;
  --t-base: 16px;
  --t-md: 18px;
  --e-out: steps(4, end);
  --e-spring: steps(6, end);
  --t-fast: 90ms;
  --t-mid: 140ms;
  --t-slow: 240ms;
}

/* Pixel keeps the grid visible: a 4px checker, so panels sit on a tile floor
   instead of a void. */
html[data-theme='pixel'] body {
  background-image: repeating-conic-gradient(#ffffff05 0% 25%, transparent 0% 50%);
  background-size: 8px 8px;
}
html[data-theme='pixel'] img,
html[data-theme='pixel'] canvas,
html[data-theme='pixel'] svg.icon {
  image-rendering: pixelated;
}
html[data-theme='pixel'] :focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

/* Several components carry a literal radius instead of a token. A pixel theme
   cannot inherit those, so the corner is squared once, globally, rather than
   leaving a stray 12px round on two panels. Scoped to the theme, and never
   inside a vendored game (that is another document). */
html[data-theme='pixel'] *:not(svg):not(svg *) {
  border-radius: 0 !important;
}

/* A 5x7 pixel face loses its legibility below 12px, and several micro labels
   are set at 9-11px. In this coat they get a floor and wider tracking instead
   of turning to mush. */
html[data-theme='pixel'] :is(.card .meta, .chip b, .hero-card-foot .meta, .hero-card-head h2,
  .hero-card-head .ticket, .side-label, .theme-pop-label, .ticker-set b, .ticker-set i,
  .tile .tag, kbd) {
  font-size: 12px;
  letter-spacing: 0.06em;
  line-height: 1.5;
}

/* ...and the same floor for the remaining micro copy: stat captions, the
   ticker, feature notes and card footers. */
html[data-theme='pixel'] :is(.stats-strip i, .stats-strip span, .ticker-set, .ticker-set b,
  .ticker-set i, .feature p, .feature h3, .foot-note, .grid-featured .meta) {
  font-size: 12px;
  line-height: 1.55;
  letter-spacing: 0.05em;
}

/* The D-pad's small R/P keys are the one place 12px type would break the pad
   rhythm; they keep their own size. */
html[data-theme='pixel'] .af-key-sm {
  font-size: 11px;
}

/* Silkscreen draws a capital A as a flat-topped triangle: at button size it
   reads as a house, and a control label that has to be decoded is not a label.
   Pad glyphs keep the rounder pixel face and gain weight instead. */
html[data-theme='pixel'] .af-key {
  font-family: 'Pixelify Sans', ui-monospace, monospace;
  font-weight: 700;
}

/* 8 · CRT — a green phosphor tube. Scanlines are a real grid, not a texture
   image, and they sit behind content so nothing is dimmed twice. */
html[data-theme='crt'] {
  color-scheme: dark;
  --ink: #04120c;
  --ink-2: #06180f;
  --panel: #082015;
  --panel-2: #0b2a1b;
  --panel-3: #103722;
  --sunk: #030e09;
  --hair: #39ff881f;
  --hair-2: #39ff8833;
  --hair-3: #39ff8859;
  --paper: #d8ffe2;
  --paper-2: #9bd6ae;
  --paper-3: #7fb894;
  --signal: #39ff88;
  --signal-2: #7dffae;
  --signal-ink: #00200d;
  --signal-text: #7dffae;
  --signal-soft: #39ff8824;
  --signal-line: #39ff8866;
  --coin: #ffcf5c;
  --coin-soft: #ffcf5c1f;
  --f-mono: 'Geist Mono', ui-monospace, monospace;
}
html[data-theme='crt'] body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 55;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    #0000004d 0px,
    #0000004d 1px,
    transparent 1px,
    transparent 3px
  );
  mix-blend-mode: multiply;
}
html[data-theme='crt'] .brand,
html[data-theme='crt'] h1,
html[data-theme='crt'] h2 {
  text-shadow: 0 0 12px #39ff8859;
}

/* 9 · Newsprint — a printed arcade page: warm stock, black ink, one red
   signal. Light chrome, so it is registered as a light theme. */
html[data-theme='newsprint'] {
  color-scheme: light;
  --ink: #f2efe4;
  --ink-2: #faf8f0;
  --panel: #fffdf6;
  --panel-2: #f4f1e6;
  --panel-3: #e8e4d6;
  --sunk: #ece8db;
  --hair: #14120e1a;
  --hair-2: #14120e2e;
  --hair-3: #14120e47;
  --paper: #14120e;
  --paper-2: #4a463c;
  --paper-3: #5c5850;
  --signal: #b3402e;
  --signal-2: #d1523d;
  --signal-ink: #fff6f2;
  --signal-text: #99301f;
  --signal-soft: #b3402e1a;
  --signal-line: #b3402e59;
  --coin: #1f5f8b;
  --coin-ink: #f2f9ff;
  --coin-text: #14507a;
  --coin-soft: #1f5f8b1a;
}

/* ============================================================
   Base
   ============================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scrollbar-color: var(--panel-3) var(--ink);
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--f-body);
  font-size: var(--t-base);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* No pull-to-refresh, anywhere. A swipe that starts on a game used to pull
     the whole page down to reload it mid-run. */
  overscroll-behavior: none;
}

html {
  overscroll-behavior: none;
}


/* One ambient wash behind everything: a lime horizon at the top. */
body::before {
  content: '';
  position: fixed;
  inset: 0 0 auto;
  height: 520px;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    70% 100% at 50% 0%,
    color-mix(in srgb, var(--signal) 9%, transparent),
    transparent 72%
  );
}

img,
svg,
video {
  max-width: 100%;
}

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

button {
  font: inherit;
  color: inherit;
}

h1,
h2,
h3,
h4 {
  font-family: var(--f-display);
  font-weight: 700;
  letter-spacing: -0.028em;
  line-height: 1.08;
  margin: 0;
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

::selection {
  background: var(--signal);
  color: var(--signal-ink);
}

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

hr {
  border: 0;
  border-top: 1px solid var(--hair);
  margin: 28px 0;
}

kbd {
  font-family: var(--f-mono);
  font-size: 10.5px;
  line-height: 1;
  padding: 4px 6px;
  border: 1px solid var(--hair-2);
  border-bottom-width: 2px;
  border-radius: 5px;
  color: var(--paper-2);
  background: var(--panel-2);
}

/* ---------------------------------------------------------- layout */

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

.skip {
  position: fixed;
  top: 8px;
  inset-inline-start: 8px;
  z-index: 200;
  transform: translateY(-160%);
  background: var(--signal);
  color: var(--signal-ink);
  font-weight: 700;
  padding: 10px 16px;
  border-radius: var(--r-sm);
  transition: transform var(--t-fast) var(--e-out);
}

.skip:focus-visible {
  transform: none;
}

/* ============================================================
   Header
   ============================================================ */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  border-bottom: 1px solid var(--hair);
  background: color-mix(in srgb, var(--ink) 86%, transparent);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
}

.site-header .bar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 18px;
  height: var(--head-h);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--f-display);
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.045em;
  white-space: nowrap;
}

.brand .mark {
  width: 30px;
  height: 30px;
  flex: 0 0 auto;
  border-radius: 9px;
  transition: transform var(--t-mid) var(--e-spring);
}

.brand:hover .mark {
  transform: rotate(-6deg) scale(1.06);
}

.brand span {
  color: inherit;
}

.brand b {
  color: var(--signal-text);
  font-weight: inherit;
}

.brand .mark {
  color: var(--signal);
}

.site-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 0;
}

.site-nav a {
  padding: 8px 11px;
  border-radius: var(--r-pill);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--paper-2);
  white-space: nowrap;
  transition:
    color var(--t-fast) var(--e-io),
    background var(--t-fast) var(--e-io);
}

.site-nav a:hover {
  color: var(--paper);
  background: var(--panel);
}

.site-nav a[aria-current='page'] {
  color: var(--paper);
  background: var(--panel-2);
}

.top-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-self: end;
}

/* ------------------------------------------------- language switcher */

/* Three codes in one row, each a real touch target.
   This used to be inline styles on the links with `flex-wrap: wrap` on the
   nav, which at 375px stacked EN/FR/AR into three rows 28px tall and left the
   search field squeezed beside them. The nav never shrinks now (`flex: 0 0
   auto`), the links never wrap, and 32px is the smallest thing a thumb hits
   reliably. */
.lang-switch {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  flex-wrap: nowrap;
  gap: 2px;
}

.lang-switch a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1;
  color: var(--paper-3);
  text-decoration: none;
  transition:
    color var(--t-fast) var(--e-io),
    background var(--t-fast) var(--e-io);
}

.lang-switch a:hover,
.lang-switch a:focus-visible {
  color: var(--paper);
  background: var(--panel);
}

/* The tree the reader is in: a filled pill reads at 32px where an outline
   set outside the box would overlap its neighbours. */
.lang-switch a[aria-current='page'] {
  color: var(--signal-ink);
  background: var(--signal);
  font-weight: 700;
}

.search {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding-block: 0;
  padding-inline: 10px 9px;
  min-width: 236px;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--paper-3);
  transition:
    border-color var(--t-fast) var(--e-io),
    background var(--t-fast) var(--e-io);
}

.search:focus-within {
  border-color: var(--signal-line);
  background: var(--panel-2);
}

.search svg {
  flex: 0 0 auto;
  opacity: 0.75;
}

.search input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: none;
  color: var(--paper);
  font: inherit;
  font-size: 13.5px;
  padding: 0;
}

.search input::placeholder {
  color: var(--paper-3);
}

.search input:focus {
  outline: none;
}

.search kbd {
  flex: 0 0 auto;
  border-bottom-width: 1px;
}

.theme-btn {
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--paper-2);
  cursor: pointer;
  transition:
    color var(--t-fast),
    border-color var(--t-fast),
    transform var(--t-fast) var(--e-spring);
}

.theme-btn:hover {
  color: var(--paper);
  border-color: var(--hair-2);
}

.theme-btn:active {
  transform: scale(0.92);
}

/* -- theme picker ------------------------------------------ */

.theme-menu {
  position: relative;
}

.theme-btn .sw,
.theme-item .sw {
  display: grid;
  place-items: center;
  border-radius: 5px;
  background: var(--sw2, var(--ink));
  box-shadow:
    inset 0 0 0 1px #ffffff26,
    0 0 0 1px var(--hair-3);
}

.theme-btn .sw::after,
.theme-item .sw::after {
  content: '';
  width: 52%;
  height: 52%;
  border-radius: 50%;
  background: var(--sw, var(--signal));
}

.theme-btn .sw {
  width: 17px;
  height: 17px;
  --sw: var(--signal);
  --sw2: var(--ink);
}

.theme-pop {
  position: absolute;
  top: calc(100% + 8px);
  inset-inline-end: 0;
  z-index: 80;
  width: 244px;
  padding: 8px;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-md);
  background: var(--panel);
  box-shadow: var(--lift-hi);
  animation: pop-in 170ms var(--e-out) both;
}

.theme-pop[hidden] {
  display: none;
}

@keyframes pop-in {
  from {
    opacity: 0;
    transform: translateY(-6px) scale(0.98);
  }
}

.theme-pop-label {
  padding: 4px 8px 8px;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper-3);
}

.theme-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--paper-2);
  font-size: 13.5px;
  text-align: start;
  cursor: pointer;
  transition:
    background var(--t-fast) var(--e-io),
    color var(--t-fast) var(--e-io);
}

.theme-item:hover,
.theme-item:focus-visible {
  background: var(--panel-2);
  color: var(--paper);
}

.theme-item[aria-checked='true'] {
  background: var(--signal-soft);
  color: var(--paper);
}

.theme-item .sw {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
}

.theme-item .nm {
  display: flex;
  flex-direction: column;
  gap: 1px;
  line-height: 1.2;
}

.theme-item em {
  font-style: normal;
  font-family: var(--f-mono);
  font-size: 10.5px;
  color: var(--paper-3);
}

.theme-item[aria-checked='true']::after {
  content: '✓';
  margin-inline-start: auto;
  color: var(--signal-text);
  font-size: 12px;
}

/* mobile nav strip: same anchors, scrolled horizontally */
.nav-strip {
  display: none;
  gap: 6px;
  padding: 0 var(--gutter) 10px;
  overflow-x: auto;
  scrollbar-width: none;
}

.nav-strip::-webkit-scrollbar {
  display: none;
}

.nav-strip a {
  flex: 0 0 auto;
  padding: 7px 13px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  font-size: 13px;
  color: var(--paper-2);
  background: var(--panel);
}

/* ============================================================
   Buttons, chips, pills
   ============================================================ */

.btn {
  --btn-bg: var(--panel);
  --btn-fg: var(--paper);
  --btn-bd: var(--hair-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: var(--tap);
  padding: 0 18px;
  border: 1px solid var(--btn-bd);
  border-radius: var(--r-md);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
  cursor: pointer;
  white-space: nowrap;
  transition:
    transform var(--t-fast) var(--e-spring),
    background var(--t-fast) var(--e-io),
    border-color var(--t-fast) var(--e-io),
    box-shadow var(--t-mid) var(--e-out),
    color var(--t-fast);
}

.btn:hover {
  --btn-bg: var(--panel-2);
  --btn-bd: var(--hair-3);
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0) scale(0.985);
}

.btn-primary {
  --btn-bg: var(--signal);
  --btn-fg: var(--signal-ink);
  --btn-bd: transparent;
  box-shadow: 0 10px 30px -14px #c9f94b99;
}

.btn-primary:hover {
  --btn-bg: var(--signal-2);
  box-shadow: 0 14px 36px -14px #c9f94bcc;
}

.btn-ghost {
  --btn-bg: transparent;
  --btn-bd: var(--hair-2);
}

.btn-ghost:hover {
  --btn-bg: var(--panel);
}

.btn svg {
  flex: 0 0 auto;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: var(--panel);
  color: var(--paper-2);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}

.pill i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--signal);
  box-shadow: 0 0 0 3px var(--signal-soft);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: var(--panel);
  color: var(--paper-2);
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition:
    color var(--t-fast),
    border-color var(--t-fast),
    background var(--t-fast),
    transform var(--t-fast) var(--e-spring);
}

.chip:hover {
  color: var(--paper);
  border-color: var(--hair-2);
  transform: translateY(-1px);
}

.chip[aria-pressed='true'],
.chip.is-on {
  color: var(--paper);
  border-color: var(--signal-line);
  background: var(--signal-soft);
}

.chip b {
  font-family: var(--f-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--paper-3);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* ============================================================
   Hero
   ============================================================ */

/* Inner pages stack: kicker, headline, paragraph, actions. The homepage
   opts into the split with .hero-split. Doing it this way means a page that
   adds a pill before its <h1> cannot silently break the grid. */
.hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding: clamp(36px, 5vw, 72px) 0 clamp(28px, 3vw, 44px);
}

.hero-split {
  display: grid;
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
}

.hero-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
  min-width: 0;
}

.hero > p:not(.kicker):not(.lede) {
  max-width: 62ch;
  font-size: var(--t-md);
  line-height: 1.6;
  color: var(--paper-2);
}

.kicker {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--f-mono);
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--paper-2);
}

.kicker i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--signal);
  box-shadow: 0 0 0 4px var(--signal-soft);
}

.hero h1 {
  font-size: var(--t-hero);
  line-height: 0.97;
  letter-spacing: -0.042em;
  margin: 0;
}

.hero h1 em {
  font-style: normal;
  color: var(--signal-text);
  position: relative;
}

.lede {
  margin: 0;
  max-width: 46ch;
  font-size: var(--t-md);
  line-height: 1.6;
  color: var(--paper-2);
}

.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.trust {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  font-size: 13px;
  color: var(--paper-3);
}

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

.trust svg {
  color: var(--signal-text);
  flex: 0 0 auto;
}

/* -- today's grid card ------------------------------------- */

.hero-card {
  position: relative;
  padding: 20px;
  border: 1px solid var(--hair);
  border-radius: var(--r-xl);
  background:
    radial-gradient(120% 90% at 100% 0%, var(--coin-soft), transparent 58%),
    linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%);
  box-shadow: var(--lift);
}

.hero-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.hero-card-head h2 {
  font-size: 16px;
  letter-spacing: -0.02em;
}

.hero-card-head .ticket {
  font-size: 10px;
}

.mini-grid {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 3px;
  padding: 10px;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--sunk);
}

.mini-grid span {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border-radius: 3px;
  font-family: var(--f-mono);
  font-size: clamp(8px, 1.1vw, 11px);
  font-weight: 500;
  color: var(--paper-2);
  text-transform: uppercase;
  user-select: none;
}

.mini-grid span.on {
  background: var(--coin);
  color: var(--coin-ink);
  font-weight: 600;
}

.hero-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
}

.hero-card-foot .meta {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--paper-3);
}

/* ============================================================
   Ticker
   ============================================================ */

.ticker {
  position: relative;
  overflow: hidden;
  border-block: 1px solid var(--hair);
  background: var(--ink-2);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.ticker-track {
  display: flex;
  width: max-content;
  animation: ticker 58s linear infinite;
}

.ticker:hover .ticker-track {
  animation-play-state: paused;
}

.ticker-set {
  display: inline-flex;
  align-items: center;
  gap: 22px;
  padding: 11px 22px 11px 0;
}

.ticker-set b {
  font-family: var(--f-mono);
  /* 11px at 0.14em tracking in --paper-3 was the weakest text on the page in
     every coat; it is body-adjacent, so it gets body-adjacent legibility. */
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--paper-2);
  white-space: nowrap;
}

.ticker-set i {
  font-style: normal;
  color: var(--signal-text);
  font-size: 10px;
}

@keyframes ticker {
  to {
    transform: translate3d(-50%, 0, 0);
  }
}

/* ============================================================
   Stat bar
   ============================================================ */

.stats-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin: 26px 0 0;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
  overflow: hidden;
}

.stats-strip span {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 16px 18px;
  border-inline-start: 1px solid var(--hair);
}

.stats-strip span:first-child {
  border-inline-start: 0;
}

.stats-strip b {
  font-family: var(--f-display);
  font-size: clamp(22px, 2.6vw, 30px);
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--paper);
}

.stats-strip i {
  font-style: normal;
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-3);
}

/* ============================================================
   Sections
   ============================================================ */

.section {
  padding: clamp(34px, 4.5vw, 56px) 0 0;
}

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.section-head h2 {
  font-size: var(--t-xl);
  letter-spacing: -0.035em;
}

.section-more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--paper-2);
  white-space: nowrap;
  transition: color var(--t-fast);
}

.section-more:hover {
  color: var(--signal-text);
}

.section-more svg {
  transition: transform var(--t-mid) var(--e-spring);
}

.section-more:hover svg {
  transform: translateX(3px);
}

/* ============================================================
   Game grid + tiles
   ============================================================ */

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

.grid-featured {
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.tile {
  --glow: var(--signal);
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px;
  min-height: 100%;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%);
  box-shadow: var(--lift);
  overflow: hidden;
  isolation: isolate;
  transition:
    transform var(--t-mid) var(--e-out),
    border-color var(--t-mid) var(--e-io),
    box-shadow var(--t-mid) var(--e-out);
}

/* the accent only ever appears as light, never as a rainbow border */
.tile::before {
  content: '';
  position: absolute;
  inset: -40% 30% 55% -20%;
  z-index: -1;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--glow) 26%, transparent), transparent);
  opacity: 0.5;
  transition: opacity var(--t-mid) var(--e-io);
}

.tile:hover {
  transform: translateY(-3px);
  border-color: var(--hair-2);
  box-shadow: var(--lift-hi);
}

.tile:hover::before {
  opacity: 1;
}

.tile:active {
  transform: translateY(-1px) scale(0.995);
}

.thumb {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 10;
  margin-bottom: 8px;
  border-radius: var(--r-md);
  background: radial-gradient(90% 80% at 50% 120%, color-mix(in srgb, var(--glow) 16%, transparent), transparent 70%);
  overflow: hidden;
}

.thumb svg,
.thumb .gicon-svg {
  width: 72px;
  height: 72px;
  border-radius: 16px;
  filter: drop-shadow(0 8px 18px color-mix(in srgb, var(--glow) 32%, transparent));
  transition: transform var(--t-mid) var(--e-spring);
}

.tile:hover .thumb svg {
  transform: translateY(-2px) scale(1.05);
}

.thumb-plain {
  font-family: var(--f-display);
  font-weight: 800;
  color: var(--coin-text);
  background: var(--sunk);
  border: 1px solid var(--hair);
}

.tile h3 {
  font-size: 15.5px;
  letter-spacing: -0.02em;
}

.tile p {
  font-size: 13px;
  line-height: 1.45;
  color: var(--paper-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tile .tag {
  align-self: flex-start;
  margin-top: 10px;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-3);
}

.tile .badge {
  position: absolute;
  top: 12px;
  inset-inline-end: 12px;
  z-index: 2;
  padding: 3px 7px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--ink) 70%, transparent);
  backdrop-filter: blur(6px);
  font-family: var(--f-mono);
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--paper-2);
}

/* ============================================================
   Category cards
   ============================================================ */

.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
}

.cat-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
  overflow: hidden;
  transition:
    transform var(--t-mid) var(--e-out),
    border-color var(--t-mid),
    background var(--t-mid);
}

.cat-card:hover {
  transform: translateY(-2px);
  border-color: var(--hair-2);
  background: var(--panel-2);
}

.cat-card .cat-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--c, var(--signal));
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--c, var(--signal)) 16%, transparent);
}

.cat-card h3 {
  font-size: 17px;
  margin-top: 8px;
}

.cat-card p {
  font-size: 13px;
  color: var(--paper-3);
  line-height: 1.45;
}

.cat-card .cat-count {
  margin-top: 10px;
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-2);
}

/* ============================================================
   Feature strip ("why")
   ============================================================ */

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 12px;
}

.feature {
  padding: 20px;
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  background: var(--panel);
}

.feature svg {
  color: var(--signal-text);
  margin-bottom: 12px;
}

.feature h3 {
  font-size: 16px;
  margin-bottom: 6px;
}

.feature p {
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--paper-3);
}

/* ============================================================
   Sponsor slots
   ============================================================ */

.ad-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px;
}

.ad-slot {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px;
  border: 1px dashed var(--hair-2);
  border-radius: var(--r-lg);
  background: var(--panel);
  transition:
    border-color var(--t-mid),
    background var(--t-mid),
    transform var(--t-mid) var(--e-out);
}

.ad-slot:hover {
  transform: translateY(-2px);
  border-color: var(--signal-line);
  background: var(--panel-2);
}

.ad-slot b {
  font-family: var(--f-display);
  font-size: 16px;
  letter-spacing: -0.02em;
}

.ad-slot span {
  font-size: 13px;
  line-height: 1.5;
  color: var(--paper-3);
}

.ad-slot em {
  margin-top: 8px;
  font-style: normal;
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-2);
}

.ad-slot.ad-real {
  border-style: solid;
  border-color: var(--hair);
  box-shadow: var(--lift);
}

.ad-slot img {
  border-radius: var(--r-sm);
  margin-bottom: 8px;
}

.sponsor {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 16px;
  margin-bottom: 20px;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  font-size: 13px;
}

.sponsor strong {
  font-size: 14px;
}

.sponsor span {
  color: var(--paper-3);
}

/* ============================================================
   Ticket / stamp
   ============================================================ */

.ticket {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--signal-line);
  border-radius: var(--r-xs);
  background: var(--signal-soft);
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--signal-text);
  white-space: nowrap;
}

/* ============================================================
   Prose, FAQ, tables, word board
   ============================================================ */

.prose {
  max-width: 68ch;
  font-size: 15px;
  color: var(--paper-2);
}

.prose h1 {
  font-size: var(--t-xl);
  color: var(--paper);
  margin: 0 0 14px;
}

.prose h2 {
  font-size: var(--t-lg);
  color: var(--paper);
  margin: 34px 0 12px;
}

.prose p {
  margin: 0 0 14px;
}

.prose a {
  color: var(--signal-text);
  text-decoration: underline;
  text-decoration-color: var(--signal-line);
  text-underline-offset: 3px;
}

.prose a:hover {
  text-decoration-color: currentColor;
}

.prose ul,
.prose ol {
  margin: 0 0 16px;
  padding-inline-start: 20px;
}

.prose li {
  margin-bottom: 7px;
}

.credit-line {
  font-size: 13px;
  color: var(--paper-3);
}

.faq {
  display: grid;
  gap: 8px;
}

.faq details {
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  overflow: hidden;
  transition: border-color var(--t-fast);
}

.faq details[open] {
  border-color: var(--hair-2);
}

.faq summary {
  padding: 14px 16px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--paper);
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

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

.faq summary::after {
  content: '+';
  font-family: var(--f-mono);
  font-size: 16px;
  color: var(--paper-3);
  transition: transform var(--t-mid) var(--e-spring);
}

.faq details[open] summary::after {
  transform: rotate(45deg);
}

.faq p {
  padding: 0 16px 15px;
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--paper-2);
}

.linklist {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.linklist a {
  padding: 7px 12px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: var(--panel);
  font-size: 13px;
  color: var(--paper-2);
  transition:
    color var(--t-fast),
    border-color var(--t-fast);
}

.linklist a:hover {
  color: var(--paper);
  border-color: var(--hair-2);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}

th {
  text-align: start;
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-3);
  font-weight: 500;
  padding: 10px 12px;
  border-bottom: 1px solid var(--hair-2);
}

td {
  padding: 11px 12px;
  border-bottom: 1px solid var(--hair);
  color: var(--paper-2);
}

tbody tr:hover td {
  background: var(--panel);
}

.answer-table a,
td a {
  color: var(--signal-text);
}

/* the solved/puzzle grid */
.board {
  display: grid;
  gap: 3px;
  padding: 12px;
  margin: 18px 0;
  width: min(100%, 520px);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--sunk);
}

.board div {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border-radius: 4px;
  font-family: var(--f-mono);
  font-size: clamp(10px, 1.6vw, 14px);
  color: var(--paper-2);
  text-transform: uppercase;
}

/* ============================================================
   Filter page
   ============================================================ */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
}

.filter-bar .filter-input {
  margin-top: 0;
  flex: 1 1 260px;
}

.sort-select {
  height: var(--tap);
  padding: 0 34px 0 14px;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--paper-2);
  font: inherit;
  font-size: 13.5px;
  cursor: pointer;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.sort-select:hover {
  color: var(--paper);
  border-color: var(--hair-3);
}

.row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 18px;
}

.filter-input {
  width: min(100%, 420px);
  height: var(--tap);
  padding: 0 16px;
  margin-top: 22px;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--paper);
  font: inherit;
  font-size: 15px;
  transition:
    border-color var(--t-fast),
    background var(--t-fast);
}

.filter-input::placeholder {
  color: var(--paper-3);
}

.filter-input:focus {
  outline: none;
  border-color: var(--signal-line);
  background: var(--panel-2);
}

.filter-status {
  min-height: 20px;
  margin-top: 10px;
  font-family: var(--f-mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--paper-3);
}

/* ----------------------------------------------------- index pager */

/* Real links, not a script: the whole catalogue stays walkable with
   JavaScript off, and every page is a URL a crawler can follow. */
.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 28px 0 4px;
}

.pager-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pager-list a,
.pager-step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 40px;
  height: 40px;
  padding: 0 13px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: var(--panel);
  color: var(--paper-2);
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition:
    color var(--t-fast),
    border-color var(--t-fast),
    background var(--t-fast);
}

.pager-list a:hover,
.pager-step:hover {
  color: var(--paper);
  border-color: var(--hair-2);
  background: var(--panel-2);
}

.pager-list a[aria-current='page'] {
  color: var(--paper);
  border-color: var(--signal-line);
  background: var(--signal-soft);
  font-weight: 600;
}

.pager-step {
  padding: 0 15px;
}

/* The top pager belongs to the filter bar, not to the section below it:
   tighter margins keep controls and results reading as one cluster. */
#game-pager-top {
  margin: 12px 0 0;
}

#index-tiles {
  padding-top: 22px;
}

/* "Showing 1–60 of 465" is a caption, not a second headline: the page's h1 is
   already above it, and at --t-xl it read as a competing title. */
#index-tiles .section-head h2 {
  font-size: var(--t-lg);
  letter-spacing: -0.02em;
}

.pager-step.is-off {
  opacity: 0.38;
}

/* One thumb on a phone: targets stay 42px, and the row keeps Prev and Next
   beside the numbers instead of stacking into three lines. A very long arcade
   scrolls the numbers sideways rather than pushing the grid down. */
@media (max-width: 560px) {
  .pager {
    flex-wrap: nowrap;
    gap: 6px;
    justify-content: space-between;
  }

  .pager-list {
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .pager-list::-webkit-scrollbar {
    display: none;
  }

  .pager-step {
    flex: 0 0 auto;
  }

  .pager-list a,
  .pager-step {
    height: 42px;
  }
}

/* A hidden result grid and a hidden page section must actually be gone: the
   .grid rule sets display, which beats the [hidden] default. */
.pager[hidden],
.grid[hidden],
#index-tiles[hidden] {
  display: none !important;
}

/* Results whose full tile is on another page. The compact card keeps the
   tile's shape so a mixed result set still reads as one grid. */
.tile-initial {
  display: grid;
  place-items: center;
  width: 72px;
  height: 72px;
  border-radius: 16px;
  font-family: var(--f-display);
  font-size: 30px;
  font-weight: 800;
  line-height: 1;
  color: var(--ink);
  background: linear-gradient(
    160deg,
    color-mix(in srgb, var(--glow) 82%, #fff) 0%,
    color-mix(in srgb, var(--glow) 46%, #000) 100%
  );
  box-shadow: 0 8px 18px color-mix(in srgb, var(--glow) 28%, transparent);
  opacity: 0.92;
  transition: transform var(--t-mid) var(--e-spring);
}

.tile:hover .tile-initial {
  transform: translateY(-2px) scale(1.05);
}

/* A result tile has no tagline, so its category label sits at the bottom of
   the card, level with the labels on the fuller cards next to it. */
.tile-remote .tag {
  margin-top: auto;
  padding-top: 10px;
}

.cat-block {
  padding-top: 34px;
}

.cat-block[hidden],
.tile[hidden],
.more-btn[hidden] {
  display: none !important;
}

.more-btn {
  display: block;
  width: 100%;
  margin-top: 12px;
  padding: 14px;
  border: 1px dashed var(--hair-2);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--paper-2);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    color var(--t-fast),
    border-color var(--t-fast),
    background var(--t-fast);
}

.more-btn:hover {
  color: var(--paper);
  border-color: var(--signal-line);
  background: var(--panel);
}

.empty {
  padding: 40px 0;
  text-align: center;
  color: var(--paper-3);
  font-size: 14px;
}

.empty b {
  display: block;
  font-family: var(--f-display);
  font-size: 20px;
  color: var(--paper);
  margin-bottom: 6px;
}

/* ============================================================
   Recently played
   ============================================================ */

#recent-section {
  display: none;
}

#recent-section.has {
  display: block;
}

.hscroll {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 6px;
  scrollbar-width: thin;
  scroll-snap-type: x proximity;
}

.recent-tile {
  flex: 0 0 auto;
  width: 104px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 12px 8px;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--panel);
  font-size: 11.5px;
  text-align: center;
  color: var(--paper-2);
  scroll-snap-align: start;
  transition:
    transform var(--t-mid) var(--e-out),
    border-color var(--t-mid);
}

.recent-tile:hover {
  transform: translateY(-2px);
  border-color: var(--hair-2);
}

.recent-tile svg {
  width: 48px;
  height: 48px;
  border-radius: 12px;
}

.recent-tile span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 88px;
}

/* ============================================================
   Footer
   ============================================================ */

.site-footer {
  margin-top: clamp(48px, 6vw, 76px);
  padding: 32px 0 44px;
  border-top: 1px solid var(--hair);
  background: var(--ink-2);
  font-size: 13.5px;
  color: var(--paper-3);
}

.site-footer .wrap {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.site-footer p {
  margin: 0;
}

.site-footer strong {
  color: var(--paper);
}

.foot-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 4px 0;
}

.foot-nav a {
  color: var(--paper-2);
  transition: color var(--t-fast);
}

.foot-nav a:hover {
  color: var(--signal-text);
}

.foot-note,
.copyright {
  font-size: 12px;
  color: var(--paper-3);
}

.foot-tips {
  color: var(--paper-2);
}

.foot-tips a {
  color: var(--signal-text);
}

/* ============================================================
   Game shell
   ============================================================ */

.game-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 372px;
  height: 100dvh;
}

#main {
  scroll-margin-top: calc(var(--head-h) + 8px);
}

.game-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  border-inline-end: 1px solid var(--hair);
}

.topbar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  flex: 0 0 auto;
  height: 58px;
  padding: 0 14px;
  border-bottom: 1px solid var(--hair);
  background: color-mix(in srgb, var(--ink) 88%, transparent);
  backdrop-filter: blur(12px);
}

.topbar .brand {
  font-size: 17px;
  justify-self: start;
}

.topbar .brand .mark {
  width: 26px;
  height: 26px;
}

.hud {
  display: flex;
  gap: 20px;
  justify-self: center;
  overflow: hidden;
}

.hud-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  line-height: 1.15;
}

.hud-label {
  font-family: var(--f-mono);
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--paper-3);
}

.hud-value {
  font-family: var(--f-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--paper);
}

.top-actions {
  display: flex;
  gap: 6px;
  justify-self: end;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--paper-2);
  cursor: pointer;
  transition:
    color var(--t-fast),
    border-color var(--t-fast),
    background var(--t-fast),
    transform var(--t-fast) var(--e-spring);
}

.icon-btn:hover {
  color: var(--paper);
  border-color: var(--hair-2);
  background: var(--panel-2);
}

.icon-btn:active {
  transform: scale(0.92);
}

.icon-btn[aria-pressed='true'] {
  color: var(--signal-text);
  border-color: var(--signal-line);
}

/* Difficulty: a segmented control, sized like the icon buttons beside it. */
.diff {
  display: inline-flex;
  align-items: stretch;
  height: 38px;
  padding: 2px;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background: var(--panel);
}

.diff-btn {
  min-width: 34px;
  padding: 0 9px;
  border: 0;
  border-radius: calc(var(--r-sm) - 2px);
  background: transparent;
  color: var(--paper-3);
  font-family: var(--f-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    color var(--t-fast),
    background var(--t-fast);
}

.diff-btn:hover {
  color: var(--paper);
  background: var(--panel-2);
}

.diff-btn[aria-pressed='true'] {
  color: var(--ink);
  background: var(--signal);
}

.diff-btn:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 1px;
}

.diff-short {
  display: none;
}

.stage {
  position: relative;
  flex: 1 1 auto;
  display: grid;
  place-items: center;
  min-height: 0;
  padding: 12px;
  background:
    radial-gradient(60% 55% at 50% 0%, color-mix(in srgb, var(--signal) 5%, transparent), transparent 70%),
    var(--ink);
  overflow: hidden;
  touch-action: none;
}

.stage canvas {
  display: block;
  max-width: 100%;
  max-height: 100%;
  border-radius: var(--r-md);
  box-shadow: 0 30px 70px -40px #000;
}

.overlay {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: none;
  place-items: center;
  padding: 20px;
  overflow-y: auto;
  background: color-mix(in srgb, var(--ink) 78%, transparent);
  backdrop-filter: blur(10px);
}

.overlay.is-open {
  display: grid;
}

.card {
  width: min(100%, 400px);
  padding: 28px 24px;
  text-align: center;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-xl);
  background: linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%);
  box-shadow: var(--lift-hi);
  animation: card-in 320ms var(--e-spring) both;
}

@keyframes card-in {
  from {
    opacity: 0;
    transform: translateY(10px) scale(0.97);
  }
}

.card h2 {
  font-size: 24px;
  letter-spacing: -0.03em;
  margin-bottom: 8px;
}

.card p {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--paper-2);
  margin-bottom: 18px;
}

.card .btn {
  width: 100%;
}

.card .row {
  display: flex;
  gap: 8px;
  margin-top: 18px;
}

.card .row .btn {
  flex: 1;
}

.card .score {
  font-family: var(--f-display);
  font-size: 56px;
  font-weight: 800;
  letter-spacing: -0.05em;
  line-height: 1;
  color: var(--signal-text);
  margin: 6px 0 4px;
}

.card .meta {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper-3);
}

.card .fine {
  margin: 16px 0 0;
  font-size: 11.5px;
  color: var(--paper-3);
}

.card .promo {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 18px;
  padding: 12px 14px;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--ink-2);
  text-align: start;
}

.card .promo strong {
  font-size: 13px;
}

.card .promo span {
  font-size: 11.5px;
  color: var(--paper-3);
}

/* -- side rail --------------------------------------------- */

.game-side {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 18px;
  min-height: 0;
  overflow-y: auto;
  background: var(--ink-2);
}

.side-head {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.side-title {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--f-display);
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -0.035em;
  color: var(--paper);
}

.side-title svg {
  width: 46px;
  height: 46px;
  flex: 0 0 auto;
  border-radius: 12px;
}

.side-tag {
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--paper-2);
}

.side-actions {
  display: grid;
  gap: 8px;
}

.side-actions .btn {
  justify-content: flex-start;
  height: 40px;
  font-size: 13.5px;
}

.side-block {
  padding-top: 14px;
  border-top: 1px solid var(--hair);
}

.side-label {
  margin-bottom: 9px;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper-3);
}

.side-links {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.side-links a {
  padding: 7px 9px;
  margin-inline: -9px;
  border-radius: var(--r-xs);
  font-size: 13.5px;
  color: var(--paper-2);
  transition:
    color var(--t-fast),
    background var(--t-fast);
}

.side-links a:hover {
  color: var(--paper);
  background: var(--panel);
}

.side-credit {
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--paper-3);
}

.side-credit a {
  color: var(--signal-text);
}

.side-foot {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--hair);
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--paper-3);
}

/* ============================================================
   Embedded (third-party) game shell
   ============================================================ */

.embed-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: 0 0 auto;
  height: 58px;
  padding: 0 14px;
  border-bottom: 1px solid var(--hair);
  background: var(--ink);
}

.embed-title {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
}

.embed-title svg {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  border-radius: 7px;
}

.embed-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.embed-open {
  margin-inline-start: 0;
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--paper-2);
}

.embed-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-inline-start: auto;
  flex: 0 0 auto;
}


.embed-open:hover {
  color: var(--signal-text);
}

.embed-stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  background: var(--ink);
}

.embed-stage iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Most of the games are other people's pages in an iframe. On a slow
   connection a blank dark panel looks like a broken site, so the frame gets a
   splash until it has actually loaded. ui.js adds .is-loaded. */
.embed-splash {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper-3);
  background: var(--ink);
  transition: opacity 240ms ease;
  pointer-events: none;
}

.embed-stage.is-loaded .embed-splash {
  opacity: 0;
}

.embed-spinner {
  width: 22px;
  height: 22px;
  border: 2px solid var(--hair-2);
  border-top-color: var(--signal);
  border-radius: 50%;
  animation: embed-spin 700ms linear infinite;
}

@keyframes embed-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .embed-spinner {
    animation: none;
  }
}

.embed-main {
  min-height: 0;
}

/* ============================================================
   Breadcrumbs
   ============================================================ */

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding-top: 18px;
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--paper-3);
}

.crumbs a {
  color: var(--paper-2);
}

.crumbs a:hover {
  color: var(--signal-text);
}

.crumbs span {
  opacity: 0.5;
}

/* ============================================================
   Motion + accessibility
   ============================================================ */

.js .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 420ms var(--e-out),
    transform 520ms var(--e-out);
  transition-delay: min(calc(var(--i, 0) * 26ms), 240ms);
}

.js .reveal.in {
  opacity: 1;
  transform: none;
}

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

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .js .reveal {
    opacity: 1;
    transform: none;
  }

  .ticker-track {
    animation: none;
  }
}

.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;
}

/* First tab stop on every page: the header nav is 8 links deep on a phone. */
.skip-link {
  position: absolute;
  top: 8px;
  inset-inline-start: 8px;
  z-index: 200;
  padding: 10px 16px;
  border-radius: var(--r-sm);
  background: var(--signal);
  color: var(--ink);
  font-weight: 700;
  text-decoration: none;
  transform: translateY(-160%);
  transition: transform 160ms var(--e-out);
}

.skip-link:focus-visible,
.skip-link:focus {
  transform: translateY(0);
  outline: 2px solid var(--paper);
  outline-offset: 2px;
}

/* ============================================================
   Responsive
   ============================================================ */

@media (max-width: 1080px) {
  .game-layout {
    grid-template-columns: minmax(0, 1fr) 320px;
  }

  .site-nav a {
    padding: 8px 9px;
    font-size: 13px;
  }

  .search {
    min-width: 180px;
  }
}

@media (max-width: 900px) {
  :root {
    --head-h: 58px;
  }

  .site-header .bar {
    grid-template-columns: auto 1fr auto;
    grid-template-areas: 'brand tools tools';
    row-gap: 0;
    height: auto;
    padding-top: 10px;
    padding-bottom: 10px;
  }

  .site-header .brand {
    grid-area: brand;
    min-width: 0;
  }

  .site-header .top-tools {
    grid-area: tools;
    flex: 1 1 auto;
    min-width: 0;
    justify-self: stretch;
  }

  .search {
    flex: 1 1 auto;
    min-width: 0;
  }

  .site-nav {
    display: none;
  }

  .nav-strip {
    display: flex;
  }

  .hero,
  .hero-split {
    grid-template-columns: 1fr;
    gap: 30px;
    padding-top: 30px;
  }

  .hero-card {
    order: 2;
  }

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

  .stats-strip span:nth-child(3) {
    border-inline-start: 0;
  }

  .stats-strip span:nth-child(n + 3) {
    border-top: 1px solid var(--hair);
  }

  /* in-game: the game is the page, the rail moves below */
  .is-game {
    height: auto;
    overflow: auto;
  }

  .game-layout {
    grid-template-columns: 1fr;
    height: auto;
    min-height: 100dvh;
  }

  .game-main {
    border-inline-end: 0;
    min-height: 62dvh;
  }

  .game-side {
    border-top: 1px solid var(--hair);
    overflow: visible;
  }

  .stage {
    min-height: 54dvh;
  }

  .embed-stage {
    min-height: 62dvh;
  }
}

@media (max-width: 620px) {
  :root {
    --gutter: 16px;
  }

  .hero h1 {
    font-size: clamp(32px, 9vw, 42px);
  }

  .lede {
    font-size: 15.5px;
  }

  .hero-cta .btn {
    flex: 1 1 auto;
  }

  .trust {
    gap: 6px 14px;
    font-size: 12px;
  }

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

  .grid-featured {
    grid-template-columns: 1fr;
  }

  .tile {
    padding: 10px;
    border-radius: var(--r-md);
  }

  .tile h3 {
    font-size: 13.5px;
    padding-inline-end: 0;
  }

  .tile p {
    font-size: 12px;
    -webkit-line-clamp: 2;
  }

  .tile .tag {
    font-size: 9px;
  }

  .thumb svg,
  .thumb .gicon-svg {
    width: 46px;
    height: 46px;
    border-radius: 12px;
  }

  .badge {
    display: none;
  }

  .section-head h2 {
    font-size: 22px;
  }

  .cat-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 9px;
  }

  .cat-card {
    padding: 13px;
  }

  .cat-card h3 {
    font-size: 14.5px;
  }

  .cat-card p {
    display: none;
  }

  /* The homepage stays a menu, not an archive: the extra tiles live on
     /games/ where the filters are. */
  #cabinet-grid .tile:nth-child(n + 13) {
    display: none;
  }

  .search kbd {
    display: none;
  }

  /* the mark carries the brand at this width; the wordmark needs the space
     for the search field */
  .site-header .brand span {
    display: none;
  }

  .topbar .brand span {
    display: none;
  }

  .hud {
    gap: 14px;
  }

  .hud-value {
    font-size: 16px;
  }

  /* Three difficulty buttons plus two icon buttons do not fit the topbar
     beside the HUD on a phone: keep the pressed level readable, shrink the
     rest to their initial. */
  .diff {
    height: 34px;
  }

  .diff-btn {
    min-width: 26px;
    padding: 0 6px;
  }

  .diff-long {
    display: none;
  }

  .diff-short {
    display: inline;
  }

  .side-title {
    font-size: 19px;
  }
}

/* Very small / landscape phones: keep the stage usable */
@media (max-height: 480px) and (orientation: landscape) {
  .stage {
    min-height: 88dvh;
  }

  .game-side {
    display: none;
  }
}

/* ============================================================
   Phone play layer
   The end of a swipe that used to be a page refresh, and the pad
   that stands in for a keyboard. Behaviour lives in public/play.js:
   this is only the shape.
   ============================================================ */

/* The scroll chain stops at the game's edge: a swipe inside the stage can
   never drag the page, and a frame that scrolls internally cannot chain its
   overscroll into a pull-to-refresh. */
.stage,
.embed-stage,
.embed-stage iframe {
  overscroll-behavior: contain;
}

body.is-immersive,
html.is-immersive {
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

/* The page becomes the game: no rail, no article, no footer. */
body.is-immersive .game-layout {
  grid-template-columns: minmax(0, 1fr);
  height: 100dvh;
}

body.is-immersive .game-side,
body.is-immersive #about,
body.is-immersive .skip-link {
  display: none;
}

body.is-immersive .embed-bar,
body.is-immersive .topbar {
  height: auto;
  min-height: 46px;
  padding-top: env(safe-area-inset-top, 0px);
}

/* The mark is the wordmark on a phone, and the HUD needs its room more. */
body.is-immersive .topbar .brand {
  display: none;
}

body.is-immersive .topbar {
  grid-template-columns: minmax(0, 1fr) auto;
}

body.is-immersive .hud {
  gap: 12px;
  justify-self: start;
  padding-inline-start: 4px;
}

body.is-immersive .hud-value {
  font-size: 15px;
}

body.is-immersive .embed-stage,
body.is-immersive .stage {
  min-height: 0;
}

/* The only way out has to be visible without scrolling. */
.af-exit {
  display: none;
  align-items: center;
  height: 34px;
  padding: 0 12px;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--paper);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

body.is-immersive .af-exit {
  display: inline-flex;
}

/* The bar has to survive four buttons on a 390px screen: in immersive the
   redundant "Open full" goes, and everything else tightens up. */
body.is-immersive .embed-open {
  display: none;
}

body.is-immersive .embed-actions {
  gap: 6px;
}

body.is-immersive .embed-bar {
  gap: 8px;
  padding-right: max(10px, env(safe-area-inset-right, 0px));
  padding-left: max(10px, env(safe-area-inset-left, 0px));
}

body.is-immersive .af-exit {
  flex: 0 0 auto;
}

/* The pad floats over the stage; the game keeps the full frame. */
.embed-stage {
  position: relative;
}

.embed-stage iframe {
  transition: height var(--t-mid) var(--e-out);
}

/* --- the pad ---------------------------------------------------------- */

.af-pad {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 70;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  padding: 0 12px calc(10px + env(safe-area-inset-bottom, 0px));
  pointer-events: none;
  transition: opacity var(--t-mid) var(--e-out);
}

.af-pad.is-off {
  visibility: hidden;
  opacity: 0;
}

.af-pad-side {
  display: grid;
  gap: 6px;
  pointer-events: auto;
}

.af-dpad {
  grid-template-columns: repeat(3, 52px);
  grid-template-rows: repeat(3, 52px);
}

.af-up {
  grid-area: 1 / 2;
}

.af-left {
  grid-area: 2 / 1;
}

.af-right {
  grid-area: 2 / 3;
}

.af-down {
  grid-area: 3 / 2;
}

.af-acts {
  grid-template-columns: repeat(2, 58px);
  grid-auto-rows: 58px;
  align-items: end;
  justify-items: center;
}

.af-key {
  -webkit-appearance: none;
  appearance: none;
  display: grid;
  place-items: center;
  min-width: 0;
  padding: 0;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--panel) 78%, transparent);
  color: var(--paper);
  font-family: var(--f-mono);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: 0 12px 30px -18px #000;
  cursor: pointer;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition:
    background var(--t-fast),
    border-color var(--t-fast),
    color var(--t-fast),
    transform var(--t-fast);
}

.af-key.is-down,
.af-key:active {
  border-color: var(--signal);
  background: var(--signal);
  color: var(--signal-ink);
  transform: scale(0.95);
}

.af-key:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

.af-key-a,
.af-key-b {
  width: 58px;
  height: 58px;
  font-size: 16px;
}

.af-key-sm {
  /* 44px is the smallest height a thumb hits reliably; the first cut used 34,
     which read as a label rather than a button on a phone. */
  width: 48px;
  height: 44px;
  font-size: 11px;
  letter-spacing: 0.06em;
}

.af-hint {
  position: fixed;
  bottom: calc(196px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  z-index: 71;
  max-width: min(92vw, 380px);
  padding: 8px 14px;
  border: 1px solid var(--hair);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  color: var(--paper-2);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-align: center;
  pointer-events: none;
  transform: translateX(-50%);
  transition: opacity var(--t-slow) var(--e-out);
}

.af-hint.is-out {
  opacity: 0;
}

/* ------------------------------------------------------------
   Pad preferences
   mode: swipe only hides the pad; hand: mirrors the two halves;
   size: a bigger thumb target for large hands or bad light.
   ------------------------------------------------------------ */

.af-gear {
  grid-column: 1 / -1;
  width: 44px;
  height: 44px;
  justify-self: end;
  font-size: 17px;
  color: var(--paper-2);
}

body.af-mode-swipe .af-pad {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
}

body.af-hand-left .af-pad {
  flex-direction: row-reverse;
}

body.af-size-lg .af-dpad {
  grid-template-columns: repeat(3, 64px);
  grid-template-rows: repeat(3, 64px);
}

body.af-size-lg .af-acts {
  grid-template-columns: repeat(2, 70px);
  grid-auto-rows: 70px;
}

body.af-size-lg .af-key-a,
body.af-size-lg .af-key-b {
  width: 70px;
  height: 70px;
  font-size: 19px;
}

body.af-size-lg .af-key-sm {
  width: 54px;
  height: 42px;
  font-size: 12px;
}

/* ------------------------------------------------------------
   Controls sheet — four rows, each one cycles on tap.
   ------------------------------------------------------------ */

.af-sheet {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: end center;
  padding: 16px;
  padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  background: #00000066;
  animation: af-sheet-in var(--t-mid) var(--e-out);
}

@keyframes af-sheet-in {
  from {
    opacity: 0;
  }
}

.af-sheet.is-out {
  opacity: 0;
  transition: opacity var(--t-fast) var(--e-out);
}

.af-sheet-in {
  width: min(100%, 420px);
  padding: 14px;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-lg);
  background: var(--panel);
  box-shadow: var(--lift-hi);
}

.af-sheet-t {
  margin: 0 0 10px;
  color: var(--paper-3);
  font-family: var(--f-mono);
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.af-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: var(--tap);
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background: var(--panel-2);
  color: var(--paper);
  font-family: var(--f-body);
  font-size: var(--t-sm);
  text-align: start;
  cursor: pointer;
}

.af-row + .af-row {
  margin-top: 8px;
}

.af-row:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

.af-row-v {
  color: var(--signal-text);
  font-family: var(--f-mono);
  font-size: var(--t-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.af-done {
  margin-top: 12px;
  background: var(--signal);
  border-color: transparent;
  color: var(--signal-ink);
  font-weight: 600;
}

.af-done .af-row-v {
  color: var(--signal-ink);
  opacity: 0.7;
}

/* Landscape: the thumbs want the sides, not the bottom. */
@media (orientation: landscape) and (max-height: 560px) {
  .af-dpad {
    grid-template-columns: repeat(3, 46px);
    grid-template-rows: repeat(3, 46px);
  }

  .af-acts {
    grid-template-columns: repeat(2, 52px);
    grid-auto-rows: 52px;
  }

  .af-key-a,
  .af-key-b {
    width: 52px;
    height: 52px;
  }

  .af-hint {
    bottom: calc(150px + env(safe-area-inset-bottom, 0px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .af-pad,
  .af-hint,
  .af-key,
  .af-sheet {
    transition: none;
    animation: none;
  }
}

/* ============================================================
   Numbers stay put
   ------------------------------------------------------------
   Scores, counters and the game surface are direction-independent: a mirrored
   "21" and a mirrored canvas are wrong answers, not a translation. Declared in
   the shared path because it is a no-op in LTR (already ltr) and a fix in RTL.
   ============================================================ */

.hud,
.hud-item,
.hud-value,
.stats-strip b,
.stage,
.stage canvas,
.embed-stage,
.embed-stage iframe {
  direction: ltr;
}

/* An isolated run so "1200" next to Arabic copy cannot be re-ordered by the
   bidi algorithm, which is what turns a score into a different score. */
.hud-value,
.stats-strip b {
  unicode-bidi: isolate;
}

/* ============================================================
   ==== Arabic typography BEGIN ====
   ------------------------------------------------------------
   Scoped to lang="ar", so the English and French trees keep Outfit,
   Bricolage and Geist Mono untouched.

   Font: Noto Sans Arabic, SIL Open Font License 1.1, self-hosted from
   /fonts as a woff2 subset holding the Arabic blocks only (no Latin glyphs).
   That absence is the trick: with 'Noto Sans Arabic' first in the stack,
   per-character fallback sends any Latin run on an Arabic page — "spielkunst",
   a game title, "FPS" — back to Bricolage/Outfit/Geist Mono, so the Latin
   voice survives inside Arabic pages instead of being replaced.
   ============================================================ */

html[lang='ar'] {
  --f-arabic: 'Noto Sans Arabic', 'Segoe UI', Tahoma, 'Arial', sans-serif;
  --f-display: 'Noto Sans Arabic', 'Bricolage Grotesque', 'Outfit', ui-sans-serif, system-ui, sans-serif;
  --f-body: 'Noto Sans Arabic', 'Outfit', ui-sans-serif, system-ui, 'Segoe UI', sans-serif;
  --f-mono: 'Noto Sans Arabic', 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}

html[lang='ar'] body {
  /* Arabic sits lower on the baseline and stacks its marks above the
     ascender: 1.55 cuts ك and ي, 1.75 does not. */
  line-height: 1.75;
}

/* Arabic is cursive. Positive tracking pulls the joins apart and negative
   tracking welds them together, so every tracked label in the design system
   (kickers, mono captions, badges, HUD labels, tile tags) releases its
   tracking on Arabic pages. (0,1,1) already beats a single class; being last
   in the file settles the ties. */
html[lang='ar'] * {
  letter-spacing: normal;
}

/* The one tracked headline scoped by an id, so it outranks the rule above. */
html[lang='ar'] #index-tiles .section-head h2,
html[lang='ar'] #game-pager-top .section-head h2 {
  letter-spacing: normal;
}

/* The wordmark is a Latin logotype on every locale: isolate it so bidi does
   not re-order "arcade" and "fork" inside an RTL line. */
html[lang='ar'] .brand {
  unicode-bidi: isolate;
}

/* ==== Arabic typography END ==== */

/* ============================================================
   ==== RTL BEGIN ====
   ------------------------------------------------------------
   Most of this file is written with logical properties already —
   margin-inline, padding-inline, inset-inline, border-inline,
   text-align: start — so dir="rtl" mirrors the header row, the card badges,
   the prose lists, the stat dividers and the pager on its own.

   What is left is the set of things a logical property cannot express: glyph
   direction, arrow-before-label order, scroll rails, and the pixel theme's
   hard offset shadows. Anything physical in here is an override on purpose.
   ============================================================ */

[dir='rtl'] body {
  /* Explicit rather than inherited: body was the one place leaning on the UA
     default, and it is the thing that decides how unattributed text falls
     out. */
  text-align: start;
}

/* -- the wordmark keeps its own direction; the grid places it on the right -- */
[dir='rtl'] .brand,
[dir='rtl'] .crumbs a {
  unicode-bidi: isolate;
}

/* -- glyphs that point along the line ------------------------------------- */
/* ‹ › around the pager, the "more" arrow, and the "/" between crumbs all
   point the wrong way once the line reads right-to-left. Mirroring the glyph
   is cheaper and more honest than shipping a second markup tree. */
[dir='rtl'] .pager-step > span,
[dir='rtl'] .crumbs > span,
[dir='rtl'] .section-more svg {
  transform: scaleX(-1);
}

/* The hover nudge has to travel the other way; scaleX is listed first so the
   positive translateX lands as a leftward move. */
[dir='rtl'] .section-more:hover svg {
  transform: scaleX(-1) translateX(3px);
}

/* -- scroll rails open on the right --------------------------------------- */
/* The 'keep playing' rail and the phone nav strip must start at the right
   edge and grow leftwards. direction is already inherited from <html>, but
   declaring it on the scroller pins the scroll origin in engines that resolve
   it per box instead of per document. */
[dir='rtl'] .hscroll,
[dir='rtl'] .nav-strip {
  direction: rtl;
}

/* -- the ticker runs the other way ---------------------------------------- */
[dir='rtl'] .ticker-track {
  animation-name: ticker-rtl;
}

@keyframes ticker-rtl {
  to {
    transform: translate3d(50%, 0, 0);
  }
}

/* -- pixel theme: hard shadows are offsets, not light --------------------- */
/* The soft themes use a symmetrical inset ring, so there is nothing to
   mirror. The pixel theme draws a 4px/4px block shadow instead, which lights
   the type from the wrong side on an RTL page. */
[dir='rtl'][data-theme='pixel'] {
  --lift: 0 0 0 2px var(--hair-3), -4px 4px 0 0 #000;
  --lift-hi: 0 0 0 2px var(--signal-line), -6px 6px 0 0 #000;
  --lift-signal: 0 0 0 2px var(--signal), -4px 4px 0 0 #000;
}

/* -- form controls keep their own start edge ------------------------------ */
/* The filter input and the sort select are native boxes with a UA-inherited
   alignment; without this they sit flush left inside an RTL toolbar. */
[dir='rtl'] .filter-input,
[dir='rtl'] .sort-select,
[dir='rtl'] .search input {
  text-align: start;
}

/* ==== RTL END ==== */
