/* ==========================================================================
   Games sub-site — /games/ (hub) and /games/<slug>/ (player shell)

   One stylesheet for both surfaces. Everything is scoped under .gm-app, so it
   can only ever touch the games pages, and every colour comes from the theme
   tokens — the sub-site follows the accent and the day/night switch with no
   values of its own.
   ========================================================================== */

.gm-app {
    --gm-radius: 10px;
    --gm-radius-lg: 12px;
    --gm-gap: 16px;
    --gm-rail: 264px;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background: hsl(var(--background));
    color: hsl(var(--foreground));
    font-family: inherit;
}

/* The `hidden` attribute is only a display hint the UA sheet supplies, so any
   rule of ours that sets display on the same element silently outranks it —
   the start screen and the loading overlay are both display:grid. */
.gm-app [hidden] { display: none !important; }

/* ── Top bar ─────────────────────────────────────────────────────────── */

/* Three columns, not two ends: the brand sits in the first, the nav in the
   middle *column* and the account controls in the last. That way the nav is
   centred on the bar itself rather than on the space left over between the
   brand and the avatar — which would drift right, since the brand is wider
   than the controls. Equal outer tracks (the 1fr in minmax(max-content, 1fr))
   are what makes the middle column genuinely the middle.

   The outer minimums are max-content, and that is the load-bearing part: with
   a plain 1fr the tracks may shrink under their contents, and once the shelf
   grows past the bar the brand and the avatar get squeezed *into* the nav.
   Flooring them at max-content means the middle column is the only one that
   gives, and it gives by scrolling its own items (`safe center` keeps the
   first one reachable) instead of overlapping its neighbours. */
.gm-top {
    position: sticky;
    top: 0;
    z-index: 30;
    display: grid;
    grid-template-columns: minmax(max-content, 1fr) minmax(0, auto) minmax(max-content, 1fr);
    align-items: center;
    gap: 12px;
    height: 56px;
    padding: 0 14px;
    /* A surface, not the page colour: the bar and the rail below it read as one
       block against the page, the way a news sidebar does. */
    background: hsl(var(--card));
    backdrop-filter: blur(10px);
    border-bottom: 1px solid hsl(var(--border));
    box-shadow: 0 1px 2px hsl(var(--foreground) / 0.04);
}

.gm-top-left,
.gm-top-right {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.gm-top-left { justify-self: start; }
.gm-top-right { justify-self: end; }

/* The site's own logo — the light/dark pair from Theme Settings, via the
   theme's helper, which also prints the link home. */
.gm-logo {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    text-decoration: none;
}

/* No `display` here — and that is deliberate. The theme's helper hides the
   light or the dark image with Tailwind's `hidden` class, which is a single
   class selector: a `display: block` of ours (one class plus one element) would
   outrank it and both logos would show at once. They are flex items, so they
   are blockified anyway and need no help. */
.gm-logo img { max-height: 36px; width: auto; }

.gm-brand {
    flex: 0 0 auto;
    padding-left: 12px;
    margin-left: 2px;
    border-left: 1px solid hsl(var(--border));
    font-size: 16px;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: hsl(var(--foreground));
    text-decoration: none;
}

/* Desktop nav: the categories, then the first few games. A shortcut into the
   shelf, so it scrolls sideways rather than wrapping as games are added.

   `safe center` is the whole trick: plain centring inside a scroller clips the
   first items once the nav is wider than the bar and makes them unreachable,
   while the safe form falls back to start-aligned exactly when that happens.
   The plain declaration before it is the fallback for engines without it. */
.gm-top-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    justify-content: safe center;
    gap: 2px;
    min-width: 0;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
}

.gm-top-nav::-webkit-scrollbar { display: none; }

.gm-top-link {
    flex: 0 0 auto;
    padding: 6px 10px;
    border-radius: 8px;
    font-size: 13.5px;
    font-weight: 600;
    color: hsl(var(--muted-foreground));
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .15s ease, color .15s ease;
}

.gm-top-link:hover {
    background: hsl(var(--muted) / 0.7);
    color: hsl(var(--foreground));
}

.gm-top-link.is-active {
    background: hsl(var(--accent));
    color: hsl(var(--accent-foreground));
    font-weight: 750;
}

.gm-top-sep {
    flex: 0 0 auto;
    width: 1px;
    height: 18px;
    margin: 0 8px;
    background: hsl(var(--border));
}

.gm-top-more { color: hsl(var(--primary)); font-weight: 700; }

/* The live run, worn by the game's own nav item: the bar doubles as a
   scoreboard, so the score is already on screen where your eye goes for the
   game's name — and the stage keeps every pixel for the game itself.

   The item only grows this readout once a run exists (the wrapper starts
   `hidden`), so an idle bar stays the plain row of links it was. */
.gm-top-game.has-live {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding-right: 11px;
}

.gm-top-live {
    display: inline-flex;
    align-items: center;
    gap: 7px;
}

.gm-top-live-num {
    font-size: 13px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
    /* Reserve the width of a full score rather than letting the number grow
       one digit at a time: otherwise every link to the right of the game you
       are playing slides sideways as you score, which is exactly when you are
       least able to tolerate a moving target. */
    min-width: 6ch;
    text-align: right;
}

/* Track + fill. The fill is a hairline rather than a chunky meter: it has to
   read at a glance from the corner of your eye while you are steering. */
.gm-top-live-bar {
    position: relative;
    display: block;
    width: 46px;
    height: 4px;
    border-radius: 999px;
    background: hsl(var(--accent-foreground) / 0.28);
    overflow: hidden;
}

.gm-top-live-bar i {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 0;
    border-radius: inherit;
    background: hsl(var(--accent-foreground));
    transition: width .2s ease;
}

/* No record to measure against yet: the track goes away rather than sitting
   there empty, and the number stands on its own. */
.gm-top-live.no-peak .gm-top-live-bar { display: none; }

/* At or past your own record the meter is full, and the item says so. */
.gm-top-live.is-best .gm-top-live-bar i { box-shadow: 0 0 0 1px hsl(var(--accent-foreground) / 0.55); }
.gm-top-live.is-paused { opacity: .62; }
.gm-top-live.is-over .gm-top-live-bar { opacity: .55; }

/* Phones: the nav is gone, so the run moves next to the account controls —
   numbers only, in an accent pill. Never both at once. */
.gm-top-live-compact { display: none; }

@media (max-width: 900px) {
    .gm-top-live-compact {
        display: inline-flex;
        align-items: center;
        padding: 5px 11px;
        border-radius: 999px;
        background: hsl(var(--accent));
        color: hsl(var(--accent-foreground));
    }
}


.gm-icon-btn {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border: 1px solid hsl(var(--border));
    border-radius: 999px;
    background: transparent;
    color: hsl(var(--muted-foreground));
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.gm-icon-btn:hover { background: hsl(var(--accent)); color: hsl(var(--accent-foreground)); }

.gm-user { display: block; text-decoration: none; }
.gm-user img, .gm-user div { border-radius: 999px; }

.gm-login {
    padding: 7px 14px;
    border-radius: 999px;
    background: hsl(var(--primary));
    color: hsl(var(--primary-foreground));
    font-size: 13px;
    font-weight: 700;
    text-decoration: none;
}

/* ── Shell: rail + main ─────────────────────────────────────────────── */

/* Full bleed, so the rail's panel can start at the screen edge. The rail pads
   itself (its items line up with the logo in the top bar) and the main column
   carries the page's own gutter. */
.gm-shell {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: var(--gm-rail) minmax(0, 1fr);
    gap: 0;
    width: 100%;
}

/* The rail below is `position: sticky`, and this is what makes that possible.

   custom.css carries `html, body { overflow-x: hidden }`, and an `overflow`
   that is not `visible` turns the element into a scroll container — a
   scrollport. <body> then becomes the scrollport every sticky descendant
   resolves against, but the body itself never scrolls: the document does. So
   the rail had nothing to stick to and simply travelled up with the article,
   which is exactly how it looked broken. `clip` clips identically without
   creating a scrollport, so the rail sticks to the viewport again.

   Same fix, same reasoning as the SERP rail (search-engine.css). Engines
   without `clip` drop this declaration and keep `hidden`, and `body.games-
   template` outweighs custom.css's bare `body` selector, so no !important. */
body.games-template { overflow-x: clip; }

/* ── Rail ───────────────────────────────────────────────────────────── */

/* The column keeps the full height of the shell, so the hairline down its right
   side reads as a spine; what sticks is the inner block. */
.gm-rail {
    align-self: stretch;
    min-width: 0;
    /* 14px matches the top bar's padding, so the first row lines up with the
       logo above it. */
    padding: 16px 14px 24px;
    background: hsl(var(--card));
    border-right: 1px solid hsl(var(--border));
}

/* The rail is pinned, and it is the *list* that scrolls — not the rail.

   It used to scroll as one block, search field and foot included, which meant
   a wheel over the sidebar moved the search box and the Back to Niguro link
   out of the window instead of moving the list you were reading. The inner is
   now a fixed-height column that hides its overflow: the search stays at the
   top, the foot stays at the bottom (margin-top: auto below), and only the nav
   between them gives.

   Sticky rather than fixed, so the rail still belongs to the shell: on a short
   page it sits where the layout puts it, and it is only once the page scrolls
   that it pins 16px under the top bar. Nothing between it and the viewport may
   set `overflow` — a scroll container there would become the sticky context
   and the rail would scroll away with the content. */
.gm-rail-inner {
    position: sticky;
    top: 72px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* A definite height, not a min-height: the children can only be laid out
       against a known box, and `margin-top: auto` on the foot needs one. */
    height: calc(100vh - 96px);
    overflow: hidden;
    padding-bottom: 6px;
}

/* Everything above and below the list is fixed. Without this the flex column
   shares the pressure between all of them, and a long list quietly squashes
   the search field instead of scrolling inside the rail. */
.gm-search,
.gm-rail-toggle,
.gm-rail-foot { flex: 0 0 auto; }

/* The one scroller: Browse, the game list, and nothing else. `min-height: 0`
   is what lets a flex child shrink below its content at all; without it the
   column grows and pushes the foot off the bottom instead of scrolling. */
.gm-rail-nav {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    padding-bottom: 4px;
    scrollbar-width: thin;
    scrollbar-color: hsl(var(--border)) transparent;
    /* Reserve the scrollbar's width whether or not it is there, so the items
       do not jump sideways the moment the list grows past the rail. */
    scrollbar-gutter: stable;
}

.gm-rail-nav::-webkit-scrollbar { width: 6px; }
.gm-rail-nav::-webkit-scrollbar-thumb {
    background: hsl(var(--border));
    border-radius: 999px;
}

/* Search */
.gm-search {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 40px;
    padding: 0 10px;
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius);
    background: hsl(var(--muted) / 0.5);
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}

.gm-search:focus-within {
    background: hsl(var(--background));
    border-color: hsl(var(--primary) / 0.5);
    box-shadow: 0 0 0 3px hsl(var(--primary) / 0.12);
}

.gm-search-icon { flex: 0 0 auto; color: hsl(var(--muted-foreground)); }

.gm-search-input {
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    border: 0;
    background: transparent;
    outline: none;
    color: hsl(var(--foreground));
    font-family: inherit;
    font-size: 13.5px;
}

.gm-search-input::placeholder { color: hsl(var(--muted-foreground)); }
.gm-search-input::-webkit-search-cancel-button { display: none; }

.gm-search-clear {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: hsl(var(--muted-foreground) / 0.15);
    color: hsl(var(--muted-foreground));
    cursor: pointer;
}

.gm-search-clear:hover {
    background: hsl(var(--muted-foreground) / 0.28);
    color: hsl(var(--foreground));
}

/* The fold control above the list, as on a news sidebar. */
.gm-rail-toggle {
    display: grid;
    place-items: center;
    width: 100%;
    height: 20px;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: hsl(var(--muted-foreground));
    cursor: pointer;
}

.gm-rail-toggle:hover {
    background: hsl(var(--muted) / 0.7);
    color: hsl(var(--foreground));
}

/* Rows */
.gm-rail-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 40px;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid transparent;
    color: hsl(var(--foreground));
    font-size: 14px;
    text-decoration: none;
    transition: background-color .15s ease, color .15s ease;
}

.gm-rail-item:hover { background: hsl(var(--muted) / 0.7); }

.gm-rail-cat.is-active,
.gm-rail-game.is-current {
    background: hsl(var(--accent));
    font-weight: 700;
}

/* The accent tick that marks where you are, inset off the row's left edge. */
.gm-rail-cat.is-active::before,
.gm-rail-game.is-current::before {
    content: '';
    position: absolute;
    left: 0;
    top: 9px;
    bottom: 9px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: hsl(var(--primary));
}

.gm-rail-count,
.gm-rail-best {
    margin-left: auto;
    font-size: 12px;
    font-weight: 700;
    color: hsl(var(--muted-foreground));
    font-variant-numeric: tabular-nums;
}

.gm-rail-best { color: hsl(var(--primary)); }

.gm-rail-nav {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.gm-rail-heading {
    margin: 2px 0 0;
    padding: 0 10px;
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: hsl(var(--muted-foreground));
}

.gm-rail-cats,
.gm-rail-list { display: flex; flex-direction: column; gap: 2px; }

.gm-rail-ico { flex: 0 0 auto; color: hsl(var(--muted-foreground)); }

.gm-rail-cat.is-active .gm-rail-ico,
.gm-rail-game.is-current .gm-rail-ico { color: hsl(var(--primary)); }

.gm-rail-label {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.gm-rail-thumb {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 7px;
    overflow: hidden;
    background: hsl(var(--muted));
}

.gm-rail-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.gm-rail-thumb i, .gm-rail-thumb svg { width: 15px; height: 15px; color: hsl(var(--muted-foreground)); }

.gm-rail-body { display: flex; flex-direction: column; min-width: 0; }

.gm-rail-title {
    font-size: 13.5px;
    line-height: 1.25;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.gm-rail-sub { font-size: 11px; color: hsl(var(--muted-foreground)); }

/* Sits at the bottom of a short rail, under a rule. */
.gm-rail-foot {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-top: 10px;
    border-top: 1px solid hsl(var(--border));
}

.gm-rail-foot .gm-rail-item {
    min-height: 36px;
    font-size: 13.5px;
    color: hsl(var(--muted-foreground));
}

.gm-rail-foot .gm-rail-item:hover { color: hsl(var(--foreground)); }

/* ── Main ───────────────────────────────────────────────────────────── */

/* No max-width: the rail is the fixed column, so the shelf is free to read as
   wide as the screen allows — `auto-fill` sets the card size, not the viewport.
   The padding is the content's margin on both sides, the same on the right as
   it is against the rail. */
.gm-main {
    display: flex;
    flex-direction: column;
    gap: 18px;
    min-width: 0;
    padding: 24px 32px 48px;
}

.gm-hero-title {
    margin: 0;
    font-size: clamp(22px, 3vw, 30px);
    font-weight: 800;
    letter-spacing: -0.02em;
}

.gm-hero-sub {
    margin: 6px 0 0;
    color: hsl(var(--muted-foreground));
    font-size: 14.5px;
}

.gm-hero-note {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 10px 0 0;
    font-size: 13px;
    color: hsl(var(--muted-foreground));
}

.gm-hero-note a { color: hsl(var(--primary)); font-weight: 700; }

/* ── Category chips ─────────────────────────────────────────────────── */

.gm-chips {
    display: flex;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 2px;
    scrollbar-width: none;
}

.gm-chips::-webkit-scrollbar { display: none; }

.gm-chip-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    padding: 7px 13px;
    border: 1px solid hsl(var(--border));
    border-radius: 999px;
    background: hsl(var(--card));
    color: hsl(var(--foreground));
    font-size: 13.5px;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.gm-chip-btn:hover { background: hsl(var(--accent)); }

.gm-chip-btn.is-active {
    background: hsl(var(--primary));
    border-color: hsl(var(--primary));
    color: hsl(var(--primary-foreground));
}

.gm-chip-num {
    font-size: 11.5px;
    font-weight: 800;
    padding: 1px 7px;
    border-radius: 999px;
    background: hsl(var(--muted));
    color: hsl(var(--muted-foreground));
}

.gm-chip-btn.is-active .gm-chip-num {
    background: hsl(var(--primary-foreground) / 0.18);
    color: hsl(var(--primary-foreground));
}

/* ── Card grid ──────────────────────────────────────────────────────── */

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

/* Wide screens carry larger tiles rather than more of them: six across on a
   1920 display lands the card at the ~250px a news sidebar's tiles sit at,
   where `200px` alone would have packed in eight narrow ones. */
@media (min-width: 1440px) {
    .gm-grid { grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); }
}

.gm-card {
    display: flex;
    flex-direction: column;
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius);
    background: hsl(var(--card));
    overflow: hidden;
    text-decoration: none;
    color: hsl(var(--foreground));
    transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}

.gm-card:hover,
.gm-card:focus-visible {
    transform: translateY(-2px);
    border-color: hsl(var(--primary) / 0.4);
    box-shadow: 0 10px 26px hsl(var(--foreground) / 0.10);
    outline: none;
}

.gm-card-media {
    position: relative;
    display: block;
    background: hsl(var(--muted));
    overflow: hidden;
}

.gm-card-media img { display: block; width: 100%; height: 100%; object-fit: cover; }

.gm-card-ph {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    background: linear-gradient(140deg, hsl(var(--primary) / 0.16), hsl(var(--accent)));
}

.gm-card-ph-letter {
    font-size: 42px;
    font-weight: 900;
    color: hsl(var(--primary));
    opacity: .85;
}

.gm-card-play {
    position: absolute;
    right: 9px;
    bottom: 9px;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    background: hsl(var(--primary));
    color: hsl(var(--primary-foreground));
    box-shadow: 0 4px 12px hsl(var(--foreground) / 0.25);
}

.gm-card-play i, .gm-card-play svg { width: 15px; height: 15px; }

.gm-card-body {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 12px 13px 14px;
}

.gm-card-title { font-size: 15.5px; font-weight: 750; line-height: 1.25; }

.gm-card-tagline {
    font-size: 12.5px;
    color: hsl(var(--muted-foreground));
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.gm-card-meta { display: flex; align-items: center; gap: 8px; margin-top: 3px; }

.gm-chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 9px;
    border-radius: 999px;
    background: hsl(var(--accent));
    color: hsl(var(--accent-foreground));
    font-size: 11.5px;
    font-weight: 750;
}

.gm-card-best {
    font-size: 11.5px;
    font-weight: 700;
    color: hsl(var(--primary));
    font-variant-numeric: tabular-nums;
}

/* ── Empty states ───────────────────────────────────────────────────── */

.gm-empty {
    border: 1px dashed hsl(var(--border));
    border-radius: var(--gm-radius-lg);
    padding: 26px 20px;
    background: hsl(var(--card));
    text-align: center;
}

.gm-empty h2 { margin: 0 0 8px; font-size: 17px; font-weight: 800; }
.gm-empty p { margin: 0; color: hsl(var(--muted-foreground)); font-size: 14px; }
.gm-empty-hint { margin-top: 8px !important; font-size: 13px !important; }
.gm-grid-empty { margin: 0; }

/* ── Player shell ───────────────────────────────────────────────────── */

/* The player page is two columns once there is room: the game and everything
   about it, then the rest of the shelf beside it. Below that the aside simply
   follows the article, and the DOM order is already the reading order. */
.gm-main-single { display: grid; grid-template-columns: minmax(0, 1fr); gap: 22px; align-items: start; }

.gm-play-col { display: flex; flex-direction: column; gap: 22px; min-width: 0; }

/* The game's own header: what it is on the left, how you are doing on the
   right. Its own panel, like every other surface on this page. */
.gm-game-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px 22px;
    flex-wrap: wrap;
    padding: 16px 18px;
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius-lg);
    background: hsl(var(--card));
}

.gm-game-head-text { min-width: 0; }

.gm-game-eyebrow {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 7px;
    margin: 0 0 9px;
}

.gm-chip-soft {
    display: inline-flex;
    align-items: center;
    padding: 2px 9px;
    border: 1px solid hsl(var(--border));
    border-radius: 999px;
    background: hsl(var(--muted) / 0.6);
    color: hsl(var(--muted-foreground));
    font-size: 11.5px;
    font-weight: 700;
}

.gm-game-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-left: auto;
}

.gm-more {
    display: flex;
    flex-direction: column;
    gap: 11px;
    padding: 14px;
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius-lg);
    background: hsl(var(--card));
}

.gm-more-title { margin: 0; font-size: 13px; font-weight: 800; letter-spacing: -.01em; }

.gm-more-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 10px; }

.gm-mini { display: flex; flex-direction: column; gap: 4px; text-decoration: none; color: hsl(var(--foreground)); }

.gm-mini-media {
    position: relative;
    display: block;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border: 1px solid hsl(var(--border));
    border-radius: 8px;
    background: hsl(var(--muted));
}

.gm-mini-media img { display: block; width: 100%; height: 100%; object-fit: cover; }

.gm-mini-title { font-size: 12.5px; font-weight: 700; line-height: 1.25; }

.gm-mini-best { font-size: 11px; color: hsl(var(--muted-foreground)); }

.gm-mini:hover .gm-mini-media { border-color: hsl(var(--primary) / 0.45); }
.gm-mini:hover .gm-mini-title { color: hsl(var(--primary)); }

.gm-more-all {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    align-self: flex-start;
    font-size: 12.5px;
    font-weight: 700;
    color: hsl(var(--primary));
    text-decoration: none;
}

.gm-more-all i { width: 15px; height: 15px; }

@media (min-width: 1280px) {
    .gm-main-single { grid-template-columns: minmax(0, 1fr) 236px; column-gap: 26px; }
    /* Stay beside the reader as the about panel scrolls past. */
    .gm-more { position: sticky; top: 88px; }
}

.gm-game-title {
    margin: 0;
    font-size: clamp(20px, 2.6vw, 27px);
    font-weight: 800;
    letter-spacing: -0.02em;
}

.gm-game-tagline { margin: 5px 0 0; color: hsl(var(--muted-foreground)); font-size: 14.5px; }

/* Your best / Runs, as two small panels rather than a line of text. */
.gm-stat {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 108px;
    padding: 10px 14px;
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius);
    background: hsl(var(--muted) / 0.5);
    line-height: 1;
}

.gm-stat-label {
    font-size: 10.5px;
    font-weight: 750;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: hsl(var(--muted-foreground));
}

.gm-stat-value { font-size: 24px; font-weight: 850; font-variant-numeric: tabular-nums; }

.gm-stage {
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* The shelf is free to run wide, but a play area should not: past this the
       16:9 frame is taller than the fold, and the controls fall off the page. */
    max-width: 1160px;
}

.gm-frame-box {
    position: relative;
    width: 100%;
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius-lg);
    background: hsl(var(--muted));
    overflow: hidden;
}

.gm-frame-box iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    background: hsl(var(--background));
}

/* A portrait game in a wide column would be an absurdly tall box: cap it and
   centre it rather than letting it run the height of the page. */
.gm-stage[data-orientation="portrait"] .gm-frame-box {
    max-width: min(430px, 100%);
    margin: 0 auto;
}

/* Start screen — the shell's own chrome, not the game's, so the instructions
   read in the theme's type and colours whatever the game's own UI looks like. */
/* Play is pinned and the instructions scroll above it, so the button is on
   screen whatever the stage's height turns out to be. */
.gm-start {
    position: absolute;
    inset: 0;
    z-index: 3;
    display: flex;
    flex-direction: column;
    padding: 16px 18px 14px;
    text-align: center;
    background: linear-gradient(160deg, hsl(var(--card)), hsl(var(--accent)));
}

.gm-start-scroll {
    display: grid;
    place-items: center;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.gm-start-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    max-width: 620px;
}

/* How-to-play and controls side by side when the stage is wide, stacked when
   it is not: the list length is what pushes a start screen out of its box. */
.gm-start-cols {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 10px 22px;
    width: 100%;
    margin-top: 4px;
}

.gm-start-col { display: flex; flex-direction: column; align-items: center; gap: 6px; }

/* Set by the host when the stage is shorter than ~470px: see fitStart() in
   assets/js/games-host.js. */
.gm-start.gm-start-compact .gm-start-poster { display: none; }
.gm-start.gm-start-compact .gm-start-inner { gap: 8px; }
.gm-start-col .gm-howto,
.gm-start-col .gm-controls { text-align: left; }

.gm-start-foot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    padding-top: 10px;
}

.gm-start-poster {
    display: block;
    width: 100%;
    max-width: 340px;
    border-radius: var(--gm-radius);
    aspect-ratio: 16/9;
    object-fit: cover;
}

.gm-start-title { margin: 0; font-size: clamp(19px, 3vw, 25px); font-weight: 850; }
.gm-start-sub { margin: 0; color: hsl(var(--muted-foreground)); font-size: 14px; }

.gm-start-label {
    margin-top: 4px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: hsl(var(--muted-foreground));
}

.gm-howto {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 5px;
    font-size: 14px;
}

.gm-howto li { position: relative; padding-left: 16px; }

.gm-howto li::before {
    content: "";
    position: absolute;
    left: 2px;
    top: 8px;
    width: 6px;
    height: 6px;
    border-radius: 999px;
    background: hsl(var(--primary));
}

.gm-controls {
    margin: 2px 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px 14px;
    font-size: 13px;
    color: hsl(var(--muted-foreground));
}

.gm-controls li { display: flex; align-items: center; gap: 7px; }

.gm-controls kbd {
    display: inline-block;
    padding: 3px 8px;
    border: 1px solid hsl(var(--border));
    border-bottom-width: 2px;
    border-radius: 7px;
    background: hsl(var(--card));
    color: hsl(var(--foreground));
    font-size: 12px;
    font-weight: 700;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.gm-play-btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 12px 26px;
    border: 0;
    border-radius: 999px;
    background: hsl(var(--primary));
    color: hsl(var(--primary-foreground));
    font-size: 15.5px;
    font-weight: 800;
    cursor: pointer;
    transition: transform .14s ease, filter .14s ease;
}

.gm-play-btn:hover { transform: translateY(-1px); filter: brightness(1.04); }

.gm-start-note { margin: 4px 0 0; font-size: 12.5px; color: hsl(var(--muted-foreground)); }

.gm-loading {
    position: absolute;
    inset: 0;
    z-index: 4;
    display: grid;
    place-items: center;
    gap: 10px;
    background: hsl(var(--muted));
    color: hsl(var(--muted-foreground));
    font-size: 14px;
}

.gm-spinner {
    width: 26px;
    height: 26px;
    border: 3px solid hsl(var(--border));
    border-top-color: hsl(var(--primary));
    border-radius: 999px;
    animation: gm-spin .8s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
    .gm-spinner { animation-duration: 1.6s; }
    .gm-card, .gm-play-btn { transition: none; }
}

/* Controls under the stage */
.gm-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 11px;
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius-lg);
    background: hsl(var(--card));
}

.gm-bar-spacer { flex: 1 1 auto; }

.gm-live {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding-right: 6px;
}

.gm-live-label {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: hsl(var(--muted-foreground));
}

.gm-live-value { font-size: 22px; font-weight: 850; font-variant-numeric: tabular-nums; }

.gm-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 13px;
    border: 1px solid hsl(var(--border));
    border-radius: 999px;
    background: transparent;
    color: hsl(var(--foreground));
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: background-color .15s ease, opacity .15s ease;
}

.gm-btn:hover:not(:disabled) { background: hsl(var(--accent)); }
.gm-btn:disabled { opacity: .45; cursor: default; }
.gm-btn.is-on { background: hsl(var(--primary)); border-color: hsl(var(--primary)); color: hsl(var(--primary-foreground)); }

.gm-save-note {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: hsl(var(--primary));
}

.gm-save-note.is-error { color: hsl(var(--destructive, 0 84% 60%)); }

/* Full screen: the stage takes the viewport and the frame fills it. */
.gm-stage.is-full {
    position: fixed;
    inset: 0;
    z-index: 120;
    padding: 10px;
    background: hsl(var(--background));
    gap: 8px;
}

.gm-stage.is-full .gm-frame-box {
    flex: 1 1 auto;
    max-width: none;
    aspect-ratio: auto !important;
    height: auto;
}

.gm-stage.is-full .gm-start { padding: 24px; }

/* A card, like the rest of the page — it carries the game's own facts, so it
   reads as a panel rather than as stray text under the controls. */
.gm-about {
    background: hsl(var(--card));
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius);
    padding: 14px 16px;
}

.gm-about h2 { margin: 0 0 8px; font-size: 14px; font-weight: 800; }

.gm-about h3 {
    margin: 18px 0 6px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: hsl(var(--muted-foreground));
}

.gm-about-facts {
    margin: 0;
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 4px 14px;
    font-size: 13.5px;
}

.gm-about dt { color: hsl(var(--muted-foreground)); }
.gm-about dd { margin: 0; font-weight: 650; }

.gm-about-list { margin: 0; padding-left: 18px; font-size: 13.5px; }
.gm-about-list li { margin: 3px 0; }

/* Controls read as key beside action, not as a bulleted list. */
.gm-about-controls {
    list-style: none;
    padding-left: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
}

.gm-about-controls li { display: flex; align-items: center; gap: 7px; margin: 0; }

.gm-about-controls kbd {
    padding: 2px 7px;
    border: 1px solid hsl(var(--border));
    border-bottom-width: 2px;
    border-radius: 6px;
    background: hsl(var(--muted));
    color: hsl(var(--foreground));
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 12px;
}

.gm-about-note { margin: 14px 0 0; font-size: 13px; color: hsl(var(--muted-foreground)); }
.gm-attribution { margin: 10px 0 0; font-size: 12.5px; color: hsl(var(--muted-foreground)); }
.gm-back { margin: 12px 0 0; font-size: 13.5px; }
.gm-back a { color: hsl(var(--primary)); font-weight: 700; text-decoration: none; }
.gm-back a:hover { text-decoration: underline; }

.gm-foot {
    margin-top: 8px;
    padding-top: 14px;
    border-top: 1px solid hsl(var(--border));
    color: hsl(var(--muted-foreground));
    font-size: 12.5px;
}

.gm-noscript { margin: 8px 0 0; font-size: 13.5px; }

/* ── Small screens ──────────────────────────────────────────────────── */

@media (max-width: 900px) {
    /* The game (and the grid) come first, the rail turns into a scroller under
       them — the same order the board uses on a phone. */
    .gm-shell {
        grid-template-columns: minmax(0, 1fr);
    }

    .gm-main {
        padding: 12px 12px 32px;
    }

    .gm-main { order: 1; }

    /* The rail stacks under the game: search, then categories and games as
       horizontal scrollers. The spine and the fold control belong to desktop.
       Its panel runs the full width of the screen — the theme's own 8px gutter
       is dropped for this shell (see custom.css) so the bar and this panel
       reach both edges, while the 12px here keeps their contents off it. */
    .gm-rail {
        order: 2;
        padding: 14px 12px 20px;
        background: hsl(var(--card));
        border-right: 0;
        border-top: 1px solid hsl(var(--border));
    }

    /* A phone has no column to pin: the rail is a block below the shelf, so the
       sticky box unwinds and the nav hands its scroller back to the page (its
       own lists scroll sideways here, not downwards). */
    .gm-rail-inner {
        position: static;
        height: auto;
        min-height: 0;
        max-height: none;
        overflow: visible;
        padding-bottom: 0;
        gap: 10px;
    }

    .gm-rail-nav {
        flex: 0 0 auto;
        overflow: visible;
        padding-bottom: 0;
        scrollbar-gutter: auto;
    }

    .gm-rail-toggle { display: none; }
    .gm-rail-heading { padding: 0; }

    /* The bar keeps the logo, the label and the account controls on a phone;
       the same links are on the rail below, and the bar has no room for both. */
    .gm-top-nav { display: none; }
    .gm-brand { border-left: 0; padding-left: 4px; }
    /* With the nav gone the middle column is empty, so the bar drops to two
       tracks rather than paying for a gap around nothing. */
    .gm-top { grid-template-columns: minmax(0, 1fr) auto; }

    .gm-rail-cats,
    .gm-rail-list {
        flex-direction: row;
        flex-wrap: nowrap;
        gap: 8px;
        overflow-x: auto;
        padding-bottom: 4px;
        scrollbar-width: none;
    }

    .gm-rail-cats::-webkit-scrollbar,
    .gm-rail-list::-webkit-scrollbar { display: none; }

    .gm-rail-item {
        flex: 0 0 auto;
        min-height: 38px;
        background: hsl(var(--muted) / 0.6);
    }

    /* A tick on the left edge of a horizontal pill reads as a glitch. */
    .gm-rail-cat.is-active::before,
    .gm-rail-game.is-current::before { display: none; }

    .gm-rail-count, .gm-rail-best { margin-left: 4px; }

    /* Stacked on a phone: a two-column definition list has no room for values
       like "Platform-owned (Niguro)". */
    .gm-about-facts { grid-template-columns: 1fr; gap: 0; }
    .gm-about-facts dt { margin-top: 9px; font-size: 12px; }
    .gm-about-facts dt:first-child { margin-top: 0; }
    .gm-about-facts dd { font-size: 14px; }

    .gm-rail-foot { flex-direction: row; gap: 8px; }
    .gm-rail-foot .gm-rail-item { flex: 0 0 auto; }

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

    .gm-frame-box { aspect-ratio: 4/3 !important; }

    .gm-stage[data-orientation="portrait"] .gm-frame-box {
        aspect-ratio: 9/16 !important;
        max-width: min(340px, 92%);
    }

    .gm-bar { flex-wrap: wrap; }
    .gm-btn span { display: none; }
    .gm-btn { padding: 9px 12px; }
    .gm-btn#gm-pause span, .gm-btn#gm-restart span { display: inline; }
    .gm-game-stats { margin-left: 0; }
    .gm-stat { flex: 1 1 auto; }
}

@media (max-width: 420px) {
    .gm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .gm-card-ph-letter { font-size: 32px; }
}

/* The hub renders inside the chrome-less shell, so make sure the theme's own
   mobile bottom nav and sidebar can never appear over it. */
body.games-template .mobile-nav,
body.games-template #left-sidebar,
body.games-template #site-header,
body.games-template #site-footer { display: none !important; }

body.games-template { background: hsl(var(--background)); }

/* ── The featured band ─────────────────────────────────────────────────── */

.gm-spot {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    align-items: center;
    gap: 22px;
    padding: 18px;
    border: 1px solid hsl(var(--border));
    border-radius: var(--gm-radius-lg);
    background: hsl(var(--card));
}

.gm-spot-media {
    position: relative;
    display: block;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--gm-radius);
    background: hsl(var(--muted));
    text-decoration: none;
}

.gm-spot-media img { display: block; width: 100%; height: 100%; object-fit: cover; }

.gm-spot-body { display: flex; flex-direction: column; gap: 9px; padding-right: 6px; }

.gm-spot-eyebrow {
    margin: 0;
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: hsl(var(--primary));
}

.gm-spot-title {
    margin: 0;
    font-size: clamp(23px, 2.3vw, 32px);
    font-weight: 850;
    line-height: 1.12;
    letter-spacing: -.02em;
}

.gm-spot-lead {
    margin: 0;
    font-size: 15px;
    line-height: 1.45;
    color: hsl(var(--muted-foreground));
}

.gm-spot-lead strong { color: hsl(var(--foreground)); font-weight: 750; }

.gm-spot-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    margin: 0;
    font-size: 13px;
    color: hsl(var(--muted-foreground));
}

.gm-spot-best { font-weight: 700; color: hsl(var(--primary)); }

.gm-spot-actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 5px 0 0; }

.gm-spot-actions .gm-btn { padding: 9px 16px; }
.gm-spot-actions .gm-btn i { width: 15px; height: 15px; }

.gm-btn-primary {
    border-color: hsl(var(--primary));
    background: hsl(var(--primary));
    color: hsl(var(--primary-foreground));
    font-weight: 750;
}

.gm-btn-primary:hover:not(:disabled) {
    background: hsl(var(--primary) / 0.88);
    color: hsl(var(--primary-foreground));
}

.gm-btn-ghost { color: hsl(var(--muted-foreground)); }
.gm-btn-ghost:hover:not(:disabled) { color: hsl(var(--foreground)); }

/* ── The shelf: one labelled row per category ──────────────────────────── */

.gm-shelf { display: flex; flex-direction: column; gap: 24px; }

/* Sectioned shelves build their own layout, so the grid's own columns are off
   and each row's track does the work. */
.gm-grid-sectioned { display: block; }

.gm-row { display: flex; flex-direction: column; gap: 12px; }

/* Sections need their own air. The grid is a plain block here, so nothing was
   separating one category from the next and every heading — "Puzzle 1" and the
   rest — sat flush on the cards of the row above it. */
.gm-grid-sectioned > .gm-row + .gm-row { margin-top: 34px; }

/* …and the first row gets a little more than the shelf's own gap, so the
   heading is not crowding the category chips. */
.gm-grid-sectioned > .gm-row:first-child { margin-top: 6px; }

.gm-row-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.gm-row-title {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 0;
    font-size: 18px;
    font-weight: 800;
    letter-spacing: -.01em;
}

.gm-row-title i { width: 18px; height: 18px; color: hsl(var(--primary)); }

.gm-row-count {
    padding: 1px 8px;
    border-radius: 999px;
    background: hsl(var(--muted));
    color: hsl(var(--muted-foreground));
    font-size: 11.5px;
    font-weight: 800;
}

.gm-row-link {
    display: inline-flex;
    align-items: center;
    gap: 1px;
    flex: 0 0 auto;
    font-size: 13px;
    font-weight: 700;
    color: hsl(var(--muted-foreground));
    text-decoration: none;
}

.gm-row-link:hover { color: hsl(var(--primary)); }
.gm-row-link i { width: 15px; height: 15px; }

.gm-row-wrap { position: relative; }

.gm-row-track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 214px);
    gap: var(--gm-gap);
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 2px;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.gm-row-track::-webkit-scrollbar { display: none; }
.gm-row-track > .gm-card { scroll-snap-align: start; }

.gm-row-next {
    position: absolute;
    top: 50%;
    right: -6px;
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    transform: translateY(-50%);
    border: 1px solid hsl(var(--border));
    border-radius: 999px;
    background: hsl(var(--card));
    color: hsl(var(--foreground));
    cursor: pointer;
    box-shadow: 0 6px 18px hsl(var(--foreground) / 0.16);
}

.gm-row-next:hover { background: hsl(var(--accent)); }
.gm-row-next i { width: 18px; height: 18px; }

/* The tracks follow the grid's own sizing so a row's cards are the same size
   as the cards in a filtered view. */
@media (min-width: 1440px) {
    .gm-row-track { grid-auto-columns: minmax(0, 232px); }
}

@media (max-width: 1023px) {
    .gm-spot { grid-template-columns: minmax(0, 1fr); gap: 16px; padding: 14px; }
}

@media (max-width: 900px) {
    .gm-row-track { grid-auto-columns: minmax(0, 168px); }
    .gm-row-next { display: none; }
}

@media (max-width: 640px) {
    .gm-shelf { gap: 20px; }
    .gm-grid-sectioned > .gm-row + .gm-row { margin-top: 26px; }
    .gm-grid-sectioned > .gm-row:first-child { margin-top: 4px; }
    .gm-row-title { font-size: 16.5px; }
    .gm-row-track { grid-auto-columns: minmax(0, 152px); }
    .gm-spot-title { font-size: 22px; }
    .gm-spot-actions .gm-btn { flex: 1 1 auto; justify-content: center; }
}
