:root {
    --bg: #060b12;
    --bg-2: #0b1420;
    --panel: #101c2b;
    --panel-2: #16283c;
    --line: #1f334a;
    --ink: #eef4fb;
    --ink-dim: #9db0c6;
    --ink-faint: #6b8199;
    /* Sampled from the logo itself: its neon is crimson (#c01830 core, blowing
       out to near-white), with the "GAMES" underline in blue. The site used to
       be cyan-led, which left the logo looking like it had been dropped in from
       another brand. Rose leads now; the blue survives as the secondary, which
       is what the logo does too. */
    --accent: #ff4d6a;
    --accent-ink: #2a0610;      /* text on a filled accent button */
    --accent-2: #6f9dff;        /* the logo's blue — links and quieter marks */
    --neon-blue: #3fd1ff;       /* the same blue the hero's pulse runs in */
    --accent-warm: #ffc861;
    --radius: 14px;
    --maxw: 1120px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-size: 17px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-2); text-decoration: none; }
a:hover { text-decoration: underline; }

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

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }

/* ---------- top bar ---------- */

.topbar {
    position: sticky;
    top: 0;
    z-index: 50;
    backdrop-filter: blur(14px);
    background: rgba(6, 11, 18, 0.78);
    border-bottom: 1px solid var(--line);
}
.topbar .wrap {
    display: flex;
    align-items: center;
    gap: 20px;
    height: 64px;
}
.brand {
    display: flex;
    align-items: center;
    gap: 11px;
    font-weight: 650;
    letter-spacing: -0.01em;
    color: var(--ink);
}
.brand:hover { text-decoration: none; }
/* The wordmark is a neon render on black, so it only sits cleanly on the dark
   bar — height-constrained rather than boxed, or it gets squashed. */
.brand img {
    height: 30px;
    width: auto;
    border-radius: 4px;
    /* Ships as neon on near-black with no alpha. `screen` drops that black into
       the header rather than leaving a visible plate around the logo. */
    mix-blend-mode: screen;
}
.brand span small {
    display: block;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink-faint);
    line-height: 1.2;
}
.navlinks { margin-left: auto; display: flex; gap: 22px; font-size: 15px; }
.navlinks a { color: var(--ink-dim); }
.navlinks a:hover { color: var(--ink); text-decoration: none; }

/* ---------- hero ---------- */

.hero {
    position: relative;
    overflow: hidden;
    padding: 92px 0 76px;
    border-bottom: 1px solid var(--line);
}
.hero::before {
    content: "";
    position: absolute;
    inset: -40% -10% auto -10%;
    height: 130%;
    background:
        radial-gradient(52% 60% at 22% 8%, rgba(255, 77, 106, 0.18), transparent 70%),
        radial-gradient(46% 56% at 82% 22%, rgba(111, 157, 255, 0.14), transparent 70%);
    pointer-events: none;
}
.hero .wrap { position: relative; }
.eyebrow {
    font-size: 12px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent);
    font-weight: 600;
    margin: 0 0 18px;
}
.hero h1 {
    margin: 0 0 20px;
    font-size: clamp(34px, 6vw, 60px);
    line-height: 1.05;
    letter-spacing: -0.03em;
    font-weight: 700;
    max-width: 16ch;
}
.hero p.lede {
    margin: 0;
    max-width: 56ch;
    font-size: clamp(17px, 2.1vw, 20px);
    color: var(--ink-dim);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }
.btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 20px;
    border-radius: 10px;
    font-weight: 600;
    font-size: 15px;
    border: 1px solid transparent;
    transition: transform 0.12s ease, background 0.15s ease, border-color 0.15s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
/* Washes from the logo's rose to the neon blue the point field pulses in, so
   the button answers the thing moving behind it. Slow on the way in, quicker on
   the way out — a hover that fades back as lazily as it arrives feels broken. */
.btn-primary {
    background: var(--accent);
    color: var(--accent-ink);
    transition: transform 0.12s ease, background-color 0.28s ease, color 0.28s ease;
}
.btn-primary:hover,
.btn-primary:focus-visible {
    background: var(--neon-blue);
    color: #04222e;
    transition: transform 0.12s ease, background-color 0.75s ease, color 0.75s ease;
}
.btn-ghost { border-color: var(--line); color: var(--ink); background: rgba(255,255,255,0.02); }
.btn-ghost:hover { border-color: var(--accent); }

.stats { display: flex; flex-wrap: wrap; gap: 40px; margin-top: 52px; }
.stat strong { display: block; font-size: 26px; letter-spacing: -0.02em; }
.stat span { font-size: 13px; color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0.08em; }

/* ---------- sections ---------- */

section { padding: 78px 0; }
.section-head { margin-bottom: 36px; }
.section-head h2 {
    margin: 0 0 10px;
    font-size: clamp(25px, 3.4vw, 34px);
    letter-spacing: -0.025em;
}
.section-head p { margin: 0; color: var(--ink-dim); max-width: 60ch; }

/* ---------- game cards ---------- */

.games { display: grid; gap: 28px; }

.game {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    gap: 0;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
}
.game-art {
    position: relative;
    min-height: 260px;
    overflow: hidden;
    background: var(--panel-2);
}
.game-art::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(100deg, rgba(6,11,18,0.05), rgba(6,11,18,0.55));
}

/* Slides stack and crossfade. Only one carries opacity 1 at a time; the rest
   stay in the flow so the panel keeps its height from the tallest of them. */
.slide {
    position: absolute;
    inset: 0;
    background-repeat: no-repeat;
    opacity: 0;
    transition: opacity 900ms ease;
}
/* A transparent slide still takes clicks, so without this the topmost slide in
   the DOM swallows every click and the lightbox opens an image other than the
   one you are looking at. */
.slide { pointer-events: none; }
.slide.is-active,
.game-art-static .slide { opacity: 1; pointer-events: auto; }
.slide-shot { background-size: cover; background-position: center; cursor: zoom-in; }
.game-body { padding: 30px 32px 32px; }
.game-title-row { display: flex; align-items: center; gap: 14px; margin-bottom: 6px; }
.game-title-row img { width: 46px; height: 46px; border-radius: 11px; flex: none; background: var(--panel-2); object-fit: cover; }
.game h3 { margin: 0; font-size: 25px; letter-spacing: -0.02em; }
.game .blurb { margin: 0 0 20px; color: var(--ink-dim); }

.badge {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.01em;
    padding: 3px 11px 3px 9px;
    border-radius: 7px;
    border: 0;
    white-space: nowrap;
}
/* One colour per promise. Releasing soon is the only near-term one, so it gets
   the go-colour; in development is the working amber; a prototype is a maybe,
   so it stays cool and quiet rather than borrowing either. */
.badge-out-now       { color: #8df3bd; background: rgba(127,240,176,0.13); }
.badge-releasing-soon{ color: #8df3bd; background: rgba(127,240,176,0.13); }
.badge-in-development{ color: var(--accent-warm); background: rgba(255,200,97,0.11); }
.badge-prototype     { color: #bdaeff; background: rgba(183,166,255,0.12); }
.badge .dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: 0.9; }

.meta { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 20px; }
.platforms { display: inline-flex; align-items: center; gap: 10px; }

/* Rendered at the size and colour they are shown at, so nothing is scaled up
   and no platform reads louder than another. Android is the head alone —
   official since the 2019 rebrand — and needs a touch more room to carry the
   same weight as the Apple silhouette; GOG is a filled square and needs less. */
.platform-mark { display: block; height: 15px; width: auto; }
.platform-android { height: 18px; }
.platform-gog { height: 14px; }


/* ---------- studio ---------- */

.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 24px; }
.card {
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 26px;
}
.card h3 { margin: 0 0 8px; font-size: 18px; letter-spacing: -0.01em; }
.card p { margin: 0; color: var(--ink-dim); font-size: 15.5px; }

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

footer {
    border-top: 1px solid var(--line);
    background: var(--bg-2);
    padding: 44px 0;
    color: var(--ink-faint);
    font-size: 14.5px;
}
footer .wrap { display: flex; flex-wrap: wrap; gap: 18px 40px; align-items: center; }
footer .spacer { margin-left: auto; }

/* ---------- lightbox ---------- */

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 100;
    background: rgba(3, 7, 12, 0.92);
    display: none;
    align-items: center;
    justify-content: center;
    padding: 32px;
    cursor: zoom-out;
}
.lightbox.open { display: flex; }
.lightbox img { max-width: min(96vw, 1100px); max-height: 92vh; border-radius: 12px; width: auto; }

/* ---------- live-reload badge ---------- */

.livebadge {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 120;
    display: none;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 999px;
    background: rgba(16, 28, 43, 0.94);
    border: 1px solid var(--line);
    color: var(--ink-dim);
    font-size: 12.5px;
    letter-spacing: 0.04em;
    backdrop-filter: blur(8px);
}
.livebadge.on { display: inline-flex; }
.livebadge .pip {
    width: 8px; height: 8px; border-radius: 50%;
    background: #57e08c;
    animation: pulse 2.4s ease-in-out infinite;
}
.livebadge.updating { color: var(--ink); border-color: var(--accent); }
.livebadge.updating .pip { background: var(--accent); animation: none; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.28; } }

@media (max-width: 860px) {
    .game { grid-template-columns: 1fr; }
    .game-art { min-height: 190px; }
    .navlinks { display: none; }
    section { padding: 56px 0; }
    .stats { gap: 28px; }
}

@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; }
    html { scroll-behavior: auto; }
}

/* ---------- engine strip ---------- */

.engine-strip {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    margin-top: 40px;
    padding: 10px 18px 10px 12px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.025);
    color: var(--ink-dim);
    font-size: 14.5px;
}
.engine-strip:hover { text-decoration: none; border-color: var(--accent); color: var(--ink); }
.engine-strip img { width: 30px; height: 30px; }
.engine-strip strong { color: var(--ink); font-weight: 650; }

/* Every card leads with a mark at the same size and weight — one card with an
   icon and three without reads as a card that is special, which it is not. */
.card-icon { width: 26px; height: 26px; margin-bottom: 12px; color: var(--accent); display: block; }
.card-engine img { width: 26px; height: 26px; margin-bottom: 12px; display: block; }

/* ---------- art fit modes ---------- */

/* Key art and logos are all different shapes, so cropping them to fill the
   panel mangles the wide ones. `contain` letterboxes onto the game's own
   accent instead; `cover` is for real screenshots, where filling is right. */
.slide.fit-contain {
    /* Contain against the bare panel: the art is as large as it can be without
       cropping. A previous version inset this 12%, which shrank every logo into
       a stamp in the middle of an empty box. */
    background-size: contain;
    background-position: center;
    background-color: color-mix(in srgb, var(--game-accent, #4fd1ff) 11%, var(--panel-2));
}
.slide.fit-cover { background-size: cover; background-position: center; }

/* A cut-out with real alpha wants the card behind it, not a tinted plate —
   a coloured box defeats the point of trimming the background off. Less
   padding too, since the art is already trimmed to its content. */
.slide.fit-logo {
    padding: 3%;
    background-origin: content-box;
    background-clip: content-box;
    background-size: contain;
    background-position: center;
}

.slide-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(145deg,
        color-mix(in srgb, var(--game-accent, #4fd1ff) 20%, var(--panel-2)),
        var(--panel-2));
}
.slide-empty span {
    font-size: clamp(22px, 3.4vw, 34px);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: rgba(255, 255, 255, 0.30);
}


.icon-stub {
    width: 46px; height: 46px; flex: none;
    display: flex; align-items: center; justify-content: center;
    border-radius: 11px;
    background: color-mix(in srgb, var(--game-accent, #4fd1ff) 26%, var(--panel-2));
    color: var(--ink);
    font-weight: 700; font-size: 21px;
}

.name-note {
    font-size: 13px;
    font-weight: 500;
    color: var(--ink-faint);
    letter-spacing: 0;
}


/* ---------- carousel ---------- */

.dots {
    position: absolute;
    left: 16px;
    bottom: 14px;
    z-index: 3;
    display: flex;
    gap: 6px;
}
.dots button {
    width: 7px;
    height: 7px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.30);
    cursor: pointer;
    transition: background 0.2s ease, transform 0.2s ease;
}
.dots button:hover { background: rgba(255, 255, 255, 0.65); }
.dots button.is-active { background: var(--game-accent, #fff); transform: scale(1.35); }

@media (prefers-reduced-motion: reduce) {
    /* No auto-advance and no crossfade — the dots still work by hand. */
    .slide { transition: none; }
}

/* ---------- lightbox gallery chrome ---------- */

.lightbox img { cursor: default; }

.lb-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 52px;
    height: 52px;
    border-radius: 50%;
    border: 1px solid var(--line);
    background: rgba(16, 28, 43, 0.88);
    color: var(--ink);
    font-size: 30px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.lb-nav:hover { background: var(--panel-2); border-color: var(--accent); }
.lb-prev { left: 24px; }
.lb-next { right: 24px; }

.lb-count {
    position: absolute;
    bottom: 26px;
    left: 50%;
    transform: translateX(-50%);
    color: var(--ink-dim);
    font-size: 13.5px;
    letter-spacing: 0.06em;
    background: rgba(16, 28, 43, 0.85);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 6px 16px;
}

@media (max-width: 700px) {
    .lb-nav { width: 42px; height: 42px; font-size: 24px; }
    .lb-prev { left: 8px; }
    .lb-next { right: 8px; }
}

/* ---------- hero point field ---------- */

#pointfield {
    position: absolute;
    top: 0;
    right: 0;
    /* Right-hand side only, and it stops short of the copy: the hero text is
       capped near 56ch, so the field lives in the space that was empty. */
    width: 58%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
    /* Faded at the left edge so it dissolves toward the text instead of ending
       on a hard vertical seam. */
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 34%, #000 100%);
    mask-image: linear-gradient(to right, transparent 0%, #000 34%, #000 100%);
}

@media (max-width: 860px) {
    /* On a phone the copy occupies the full width; a field behind it is just
       noise under text. */
    #pointfield { display: none; }
}

/* The updated stamp is a real <time> so it is machine-readable, and it is its
   own footer item rather than tacked onto the licence line — it answers "is
   this page current", which is a different question from who owns the logo. */
.updated { color: var(--ink-faint); }
.updated time { color: var(--ink-dim); }
