/* UNLATCH GAMES — the portal.
 *
 * THE BRIEF THIS IS BUILT TO: hundreds of games, found fast. That is a
 * different job from a studio one-pager, and it drives every decision here:
 *
 *   - DARK FIRST. A games portal is a wall of bright thumbnails; a dark ground
 *     is what lets them carry the colour instead of fighting the page for it.
 *     Light is a supported theme, not the design target.
 *   - DENSE. Tiles, not cards with paragraphs. Six to eight per row on a
 *     desktop, two on a phone, and a rail that scrolls sideways for a
 *     shelf of twenty. Text per tile is a name and a kind.
 *   - DATA, NOT MARKUP. Nothing about a game is written into a page. The grid
 *     is rendered from `games.js`, so game 300 costs one row of data.
 *   - THE TILES PLAY. Every thumbnail loops its game's actual move
 *     (`previews.js`), which is the one thing a portal can do that a shelf of
 *     screenshots cannot.
 *
 * WHAT IS KEPT from the studio's handwriting: the coral, the rounded shapes,
 * and the games themselves, which are still drawn in ink and hard shadow
 * inside their own frame. The chrome around them is not: an ink outline and a
 * 6px offset shadow on two hundred tiles is noise, and it was the first thing
 * that made this page look like a toy rather than a place to find a game.
 */

@font-face {
  font-family: "Fredoka Display";
  src: url("/assets/fonts/Fredoka-display.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------- the tokens */

:root {
  /* Dark is the design target, so it is the root. */
  --bg: #0b0d14;
  --bg-2: #0f121b;
  --surface: #161a26;
  --surface-2: #1d2231;
  --surface-3: #262c3d;
  --line: rgba(255, 255, 255, .09);
  --line-strong: rgba(255, 255, 255, .16);

  --text: #f3f5fa;
  --dim: #a6adbf;
  --faint: #6f7789;

  --accent: #ff5d3b;
  --accent-2: #8b5cf6;
  --accent-ink: #14060a;
  --mint: #3ddba2;
  --sun: #ffc63d;
  --sky: #56b8ff;

  --glow: 0 0 0 1px var(--line), 0 12px 32px rgba(0, 0, 0, .55);
  --glow-hover: 0 0 0 1px var(--line-strong), 0 18px 44px rgba(0, 0, 0, .62);

  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 26px;
  --r-pill: 999px;

  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-5: 24px; --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 88px;

  --wrap: 1400px;
  --head: 64px;

  /* The UI face is the system's: on a portal it is the fastest thing that can
   * possibly load, and it is what every platform's own store already uses.
   * Fredoka is kept for the wordmark and the big headings, because that is
   * the studio's voice and it costs 25 KB once. */
  --ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, "Helvetica Neue", Arial, sans-serif;
  --display: "Fredoka Display", var(--ui);

  color-scheme: dark;
}

:root[data-theme="light"] {
  --bg: #f4f5f8;
  --bg-2: #ffffff;
  --surface: #ffffff;
  --surface-2: #f0f2f6;
  --surface-3: #e5e8ef;
  --line: rgba(16, 20, 34, .10);
  --line-strong: rgba(16, 20, 34, .20);

  --text: #131725;
  --dim: #566077;
  --faint: #8a92a6;

  --accent: #f2451c;
  --accent-2: #7c3aed;
  --accent-ink: #fff6f3;

  --glow: 0 0 0 1px var(--line), 0 8px 24px rgba(16, 20, 34, .10);
  --glow-hover: 0 0 0 1px var(--line-strong), 0 14px 34px rgba(16, 20, 34, .16);

  color-scheme: light;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: #f4f5f8;
    --bg-2: #ffffff;
    --surface: #ffffff;
    --surface-2: #f0f2f6;
    --surface-3: #e5e8ef;
    --line: rgba(16, 20, 34, .10);
    --line-strong: rgba(16, 20, 34, .20);
    --text: #131725;
    --dim: #566077;
    --faint: #8a92a6;
    --accent: #f2451c;
    --accent-2: #7c3aed;
    --accent-ink: #fff6f3;
    --glow: 0 0 0 1px var(--line), 0 8px 24px rgba(16, 20, 34, .10);
    --glow-hover: 0 0 0 1px var(--line-strong), 0 14px 34px rgba(16, 20, 34, .16);
    color-scheme: light;
  }
}

/* ----------------------------------------------------------------- the base */

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--ui);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}

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

a { color: inherit; text-decoration: none; }
img, svg, canvas { display: block; }
/* The browser's own [hidden] rule loses to any class that sets display
   (.tile is display:block), so filter and search hid tiles nobody saw go. */
[hidden] { display: none !important; }

:where(a, button, input, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: clamp(16px, 3vw, 32px); }

h1, h2, h3 { margin: 0; line-height: 1.12; letter-spacing: -0.02em; }
h1 { font-family: var(--display); font-weight: 600; font-size: clamp(30px, 4vw, 50px); }
h2 { font-family: var(--display); font-weight: 600; font-size: clamp(20px, 2vw, 27px); }
h3 { font-size: 15px; font-weight: 650; letter-spacing: -0.01em; }

.muted { color: var(--dim); }
.lead { color: var(--dim); font-size: clamp(15px, 1.2vw, 17px); max-width: 60ch; margin: var(--s-3) 0 0; }

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

header.top {
  position: sticky; top: 0; z-index: 40;
  height: var(--head);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid var(--line);
}
.top .wrap { height: 100%; display: flex; align-items: center; gap: var(--s-4); }

.logo { display: inline-flex; align-items: center; gap: 10px; flex: none; }
.logo .mark {
  width: 32px; height: 32px; border-radius: 9px;
  background: linear-gradient(140deg, var(--accent), var(--accent-2));
  color: #fff; display: grid; place-items: center;
  font-family: var(--display); font-size: 19px; line-height: 1;
}
.logo .word { font-family: var(--display); font-size: 19px; letter-spacing: -0.02em; white-space: nowrap; }
.logo .word b { font-weight: inherit; color: var(--accent); }

/* SEARCH IS THE PRIMARY NAVIGATION once there are more games than fit on a
 * screen, so it lives in the header on every page rather than on one of them. */
.search { position: relative; flex: 1; max-width: 420px; margin-left: var(--s-2); }
.search input {
  width: 100%; height: 38px;
  padding: 0 var(--s-4) 0 38px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  font: inherit; font-size: 14px;
}
.search input::placeholder { color: var(--faint); }
.search input:focus { outline: none; border-color: var(--accent); background: var(--surface-2); }
.search > svg { position: absolute; left: 13px; top: 50%; translate: 0 -50%; width: 16px; height: 16px; color: var(--faint); }
/* Live results under the box, on every page but the catalogue (catalogue.js). */
.suggest {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 50;
  padding: var(--s-1);
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .28);
}
.suggest a { display: flex; align-items: center; gap: var(--s-3); padding: 6px var(--s-2); border-radius: var(--r-sm); }
.suggest a:hover, .suggest a:focus-visible { background: var(--surface-3); }
.suggest .mark { flex: none; width: 32px; height: 32px; border-radius: var(--r-sm); display: grid; place-items: center; }
.suggest .mark svg { width: 22px; height: 22px; }
.suggest b { font-size: 14px; }
.suggest small { margin-left: auto; color: var(--faint); font-size: 12px; font-weight: 600; }
.suggest .more { justify-content: center; color: var(--accent); font-size: 13px; font-weight: 700; }
.suggest p.more { color: var(--faint); padding: var(--s-3); margin: 0; text-align: center; font-weight: 600; }

nav.links { display: flex; align-items: center; gap: var(--s-1); margin-left: auto; }
.navlink {
  padding: 7px 12px; border-radius: var(--r-sm);
  font-size: 14px; font-weight: 600; color: var(--dim);
  transition: color .15s, background .15s;
}
.navlink:hover { color: var(--text); background: var(--surface-2); }
.navlink[aria-current="page"] { color: var(--text); background: var(--surface-2); }

.icon-btn {
  width: 36px; height: 36px; flex: none; padding: 0; cursor: pointer;
  border-radius: var(--r-sm); border: 1px solid var(--line);
  background: var(--surface); color: var(--dim);
  display: grid; place-items: center;
  transition: color .15s, background .15s, border-color .15s;
}
.icon-btn:hover { color: var(--text); background: var(--surface-2); border-color: var(--line-strong); }
.icon-btn svg { width: 17px; height: 17px; display: none; }
:root[data-theme="light"] .icon-btn .moon { display: block; }
:root[data-theme="dark"] .icon-btn .sun { display: block; }
:root:not([data-theme]) .icon-btn .sun { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .icon-btn .sun { display: none; }
  :root:not([data-theme]) .icon-btn .moon { display: block; }
}

/* ----------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  height: 44px; padding: 0 22px; border-radius: var(--r-pill);
  border: 1px solid transparent; background: var(--surface-2); color: var(--text);
  font: inherit; font-size: 15px; font-weight: 650; cursor: pointer;
  transition: transform .15s, background .15s, box-shadow .15s;
}
.btn:hover { transform: translateY(-1px); background: var(--surface-3); }
.btn.primary {
  background: linear-gradient(135deg, var(--accent), #ff8a3d);
  color: #fff; box-shadow: 0 8px 24px rgba(255, 93, 59, .30);
}
.btn.primary:hover { box-shadow: 0 12px 30px rgba(255, 93, 59, .42); }
.btn.quiet { background: transparent; border-color: var(--line-strong); color: var(--dim); }
.btn.quiet:hover { color: var(--text); background: var(--surface-2); }
.btn svg { width: 17px; height: 17px; }

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

.hero {
  position: relative; overflow: hidden;
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--glow);
  margin-top: var(--s-5);
  display: grid; gap: 0;
  grid-template-columns: 1fr;
}
@media (min-width: 860px) { .hero { grid-template-columns: 1.02fr 1fr; } }

.hero .copy { padding: clamp(24px, 3.4vw, 48px); display: flex; flex-direction: column; justify-content: center; }
.hero .tagline { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.hero h1 { margin: var(--s-3) 0 0; }
.hero .actions { display: flex; gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-5); }
.hero .meta { display: flex; gap: var(--s-4); flex-wrap: wrap; margin-top: var(--s-5); color: var(--faint); font-size: 13px; font-weight: 600; }
.hero .meta b { color: var(--dim); font-weight: 650; }

.hero .stage { position: relative; min-height: 280px; }
.hero .stage canvas, .hero .stage svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero .stage svg { padding: 18%; }
/* Only enough of a wash to seat the art against the copy. The first pass ran
 * it to 42% and swallowed half the animation. */
.hero .stage::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, var(--surface) 0%, transparent 22%);
}
@media (max-width: 859px) {
  .hero .stage { aspect-ratio: 16 / 10; min-height: 0; }
  .hero .stage::after { background: linear-gradient(0deg, var(--surface) 0%, transparent 26%); }
}

/* ------------------------------------------------------------------ shelves */

.shelf { margin-top: var(--s-8); }
.shelf-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4); margin-bottom: var(--s-4); }
.shelf-head .count { color: var(--faint); font-size: 13px; font-weight: 600; }
.shelf-head a { color: var(--dim); font-size: 14px; font-weight: 650; }
.shelf-head a:hover { color: var(--accent); }

/* A rail for a shelf of twenty: it scrolls sideways and snaps, which is what a
 * portal does with a row it cannot fit. */
.rail {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: clamp(150px, 21vw, 200px);
  gap: var(--s-4);
  overflow-x: auto; scroll-snap-type: x proximity;
  padding-bottom: var(--s-3);
  scrollbar-width: thin; scrollbar-color: var(--surface-3) transparent;
}
.rail > * { scroll-snap-align: start; }
.rail::-webkit-scrollbar { height: 8px; }
.rail::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: var(--r-pill); }
.rail::-webkit-scrollbar-track { background: transparent; }

/* THE GRID THAT HAS TO HOLD HUNDREDS. Tiles size themselves, so the same rule
 * gives two columns on a phone and eight on a wide desktop. */
.grid {
  display: grid; gap: clamp(12px, 1.4vw, 20px);
  grid-template-columns: repeat(auto-fill, minmax(clamp(140px, 15vw, 190px), 1fr));
}

/* ------------------------------------------------------------------- tiles */

.tile { display: block; position: relative; }
.tile .thumb {
  position: relative; aspect-ratio: 1;
  border-radius: var(--r-lg); overflow: hidden;
  background: var(--surface-2);
  /* A SECOND RING, INSIDE. Four games are painted near-white (Pixel Pantry
   * #fdf7ec, Slant Slope #f2f0e6, Conquest #f4ead3, Tile Tussle #bfe9ff) and
   * the light page is #f4f5f8, so --glow's 10% outer hairline left those tiles
   * with no edge at all. --line-strong flips with the theme, which is what the
   * dark tiles need on a dark page for the same reason. */
  box-shadow: var(--glow), inset 0 0 0 1px var(--line-strong);
  transition: transform .2s cubic-bezier(.2,.9,.3,1.2), box-shadow .2s;
}
.tile:hover .thumb, .tile:focus-visible .thumb { transform: translateY(-4px) scale(1.02); box-shadow: var(--glow-hover), inset 0 0 0 1px var(--line-strong); }
.tile .thumb canvas, .tile .thumb svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.tile .thumb svg { padding: 26%; transition: opacity .35s ease; }
/* The mark is the poster: it is what shows with no JavaScript, before a
 * preview has drawn, and for anyone who asked for less motion. It steps aside
 * only once a canvas is actually running. */
.thumb .preview, .stage .preview { opacity: 0; transition: opacity .45s ease; }
.thumb.playing .preview, .stage.playing .preview { opacity: 1; }
.thumb.playing > svg, .stage.playing > svg { opacity: 0; }

/* The play affordance: a portal tile is a button, and it should look like one
 * the moment a pointer is near it. */
.tile .go {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: linear-gradient(180deg, rgba(6,8,14,0) 35%, rgba(6,8,14,.72));
  opacity: 0; transition: opacity .2s;
}
.tile:hover .go, .tile:focus-visible .go { opacity: 1; }
.tile .go span {
  display: inline-flex; align-items: center; gap: 7px;
  background: #fff; color: #12141c;
  padding: 8px 16px; border-radius: var(--r-pill);
  font-size: 13px; font-weight: 700;
}
.tile .badge {
  position: absolute; top: 9px; left: 9px; z-index: 2;
  padding: 3px 9px; border-radius: var(--r-pill);
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  background: var(--accent); color: #fff;
}
.tile .badge.daily { background: var(--sky); color: #06121d; }
.tile .meta { padding: 10px 2px 0; }
.tile .meta h3 { color: var(--text); }
.tile .meta p { margin: 2px 0 0; color: var(--faint); font-size: 12.5px; font-weight: 600; }

/* A tile on a rail keeps its name under it, the same as one in the grid. */
.rail .tile .thumb { aspect-ratio: 1; }

/* ------------------------------------------------------------------ filters */

.toolbar {
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
  margin: var(--s-5) 0 var(--s-5);
}
.chips { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.chip {
  padding: 7px 14px; border-radius: var(--r-pill);
  border: 1px solid var(--line); background: var(--surface);
  color: var(--dim); font: inherit; font-size: 13.5px; font-weight: 650; cursor: pointer;
  transition: color .15s, background .15s, border-color .15s;
}
.chip:hover { color: var(--text); border-color: var(--line-strong); }
.chip[aria-pressed="true"] { background: var(--accent); border-color: transparent; color: #fff; }

.empty { color: var(--faint); padding: var(--s-8) 0; text-align: center; }

/* -------------------------------------------------------------------- rows */

.strip-facts {
  display: grid; gap: var(--s-3);
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  margin-top: var(--s-8);
}
.factcard {
  background: var(--surface); border-radius: var(--r-lg);
  box-shadow: var(--glow); padding: var(--s-4) var(--s-5);
}
.factcard b { display: block; font-family: var(--display); font-weight: 600; font-size: 26px; line-height: 1.1; }
.factcard span { color: var(--faint); font-size: 12.5px; font-weight: 600; }

.prose { max-width: 68ch; }
.prose p { color: var(--dim); margin: var(--s-4) 0 0; }
.prose h2 { margin-top: var(--s-7); }
.prose h2:first-child { margin-top: 0; }
.prose a { color: var(--accent); font-weight: 650; }
.prose strong { color: var(--text); }

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

footer.bottom { margin-top: var(--s-9); border-top: 1px solid var(--line); background: var(--bg-2); }
footer.bottom .wrap { display: grid; gap: var(--s-6); grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); padding-block: var(--s-7) var(--s-5); }
footer.bottom .brand { grid-column: 1 / -1; }
@media (min-width: 720px) { footer.bottom .brand { grid-column: span 2; } }
footer.bottom p { color: var(--faint); font-size: 13.5px; margin: var(--s-3) 0 0; max-width: 38ch; }
footer.bottom h4 { margin: 0 0 var(--s-3); font-size: 11.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--faint); }
footer.bottom ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
footer.bottom li a { color: var(--dim); font-size: 14px; }
footer.bottom li a:hover { color: var(--accent); }
.endbar { border-top: 1px solid var(--line); }
.endbar .wrap { display: flex; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap; padding-block: var(--s-4); color: var(--faint); font-size: 12.5px; }

/* ------------------------------------------------------------------- frame */

.frame { border: 0; width: 100%; height: calc(100dvh - var(--head)); background: #000; }

@media (max-width: 700px) {
  .search { max-width: none; }
  nav.links .navlink { display: none; }
  /* The box is narrow here; the results take the width under the header. */
  .suggest { position: fixed; top: calc(var(--head) + 4px); left: 16px; right: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

/* ============================================================================
 * THE BRAND LAYER
 *
 * Everything above this line is furniture: it makes a dark portal that could
 * belong to anybody. This is the part that could only be ours.
 *
 * The idea in the name is the whole identity. To UNLATCH is to open something
 * that was shut — no key, no account, no install, just a catch lifting. So:
 *
 *   THE MARK    a `u` whose right stem has swung open, like a clasp
 *   THE SEAM    a hairline rule with a notch bitten out of it, the line where
 *               a thing opens; it heads every shelf and underlines the hero
 *   THE LAMP    one warm light behind the page, so the ground is a room and
 *               not a swatch
 *
 * The rule for all three: they are drawn in CSS and SVG, cost no request, and
 * are the same two colours the tiles already use.
 * ========================================================================= */

:root {
  --brand-glow: radial-gradient(80rem 40rem at 12% -12%, color-mix(in srgb, var(--accent) 20%, transparent), transparent 62%),
                radial-gradient(60rem 34rem at 92% 4%, color-mix(in srgb, var(--accent-2) 18%, transparent), transparent 58%);
  --seam: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent-2) 78%, transparent) 42%, transparent);
}

/* THE LAMP. A flat ground is what made this look like a template. One warm
 * wash from the upper left and one cool one from the upper right give the page
 * a light source, and every card on it something to sit against. It is fixed,
 * so scrolling moves the content through the light rather than dragging the
 * light along with it. */
body::before {
  content: "";
  position: fixed; inset: 0;
  background: var(--brand-glow);
  pointer-events: none;
  z-index: 0;
}
/* On the dark ground a 20% wash is a glow; on the light one it is nothing at
   all, because there is no dark to lift. Light gets a stronger, tighter tint
   and a top band, which is what stops the page reading as a blank sheet. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --brand-glow:
      linear-gradient(180deg, color-mix(in srgb, var(--accent) 7%, transparent), transparent 340px),
      radial-gradient(52rem 26rem at 8% -6%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 60%),
      radial-gradient(44rem 24rem at 96% -2%, color-mix(in srgb, var(--accent-2) 14%, transparent), transparent 58%);
  }
}
:root[data-theme="light"] {
  --brand-glow:
    linear-gradient(180deg, color-mix(in srgb, var(--accent) 7%, transparent), transparent 340px),
    radial-gradient(52rem 26rem at 8% -6%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 60%),
    radial-gradient(44rem 24rem at 96% -2%, color-mix(in srgb, var(--accent-2) 14%, transparent), transparent 58%);
}
body > * { position: relative; z-index: 1; }

/* THE MARK. The gradient square with a letter in it was a placeholder that
 * shipped. This is the clasp the studio is named after: a `u` bowl, and a
 * right stem hinged at the bowl's end and swung open. It is one inline SVG in
 * a background — no request, no markup change on three pages, and it scales
 * to the footer and the favicon without a second copy. */
.logo .mark {
  background: linear-gradient(140deg, var(--accent), var(--accent-2));
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 30%, transparent);
  position: relative;
  font-size: 0;                     /* the `u` in the markup is the fallback */
}
.logo .mark::before {
  content: "";
  position: absolute; inset: 0;
  background: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2032%2032'%3E%3Cg%20fill='none'%20stroke='%23fff'%20stroke-width='2.9'%20stroke-linecap='round'%3E%3Cpath%20d='M10%208%20V16.5%20A5.5%205.5%200%200%200%2021%2016.5'/%3E%3Cpath%20d='M21%2016.5%20V8.5'%20transform='rotate(24%2021%2016.5)'/%3E%3C/g%3E%3C/svg%3E") center / 100% 100% no-repeat;
  transition: background-image .2s steps(1);
}
/* The catch lifts a little further when you reach for it. */
.logo:hover .mark::before {
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2032%2032'%3E%3Cg%20fill='none'%20stroke='%23fff'%20stroke-width='2.9'%20stroke-linecap='round'%3E%3Cpath%20d='M10%208%20V16.5%20A5.5%205.5%200%200%200%2021%2016.5'/%3E%3Cpath%20d='M21%2016.5%20V8.5'%20transform='rotate(40%2021%2016.5)'/%3E%3C/g%3E%3C/svg%3E");
}

.logo .word { font-weight: 600; }
.logo .word b { color: var(--accent); font-weight: 600; }

/* THE SEAM. A shelf heading with a rule beside it reads as a template. A rule
 * with a NOTCH in it reads as a lid about to lift, which is the one thing this
 * studio is called. It is one gradient and one mask — no image, no request. */
.shelf-head { position: relative; }
.shelf-head::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -10px;
  height: 2px;
  background: var(--seam);
  -webkit-mask: radial-gradient(circle 7px at 34px 50%, transparent 98%, #000 100%);
  mask: radial-gradient(circle 7px at 34px 50%, transparent 98%, #000 100%);
  opacity: .75;
}

/* The hero carries the same seam, full width, as the line the panel opens on. */
.hero { position: relative; overflow: hidden; }
.hero::after {
  content: "";
  position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--seam);
  -webkit-mask: radial-gradient(circle 9px at 60px 50%, transparent 98%, #000 100%);
  mask: radial-gradient(circle 9px at 60px 50%, transparent 98%, #000 100%);
}

/* THE STUDIO LINE. The hero was a game card the size of a billboard and said
 * nothing about whose site this is. One line above the title, in the mark's
 * own colours, is enough — and it is the promise the whole catalogue is built
 * on, so it is worth the four words. */
.hero .copy { position: relative; }
/* The kicker and the game's badge are one line, in that order: whose site
   this is, then what is new on it. Stacked, they read as two false starts. */
.hero .kicker + .tagline { margin-left: 10px; padding-left: 10px; border-left: 2px solid var(--line-strong); }
.hero .kicker, .hero .tagline { vertical-align: middle; }
.hero .kicker {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent);
}
.hero .kicker::before {
  content: ""; width: 16px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}

/* A TILE SHOULD LIFT, not just brighten. The catch coming open is the studio's
 * one gesture, so it is the gesture a card makes when you reach for it. */
.tile { transition: transform .18s cubic-bezier(.34, 1.3, .5, 1), box-shadow .18s ease; }
.tile:hover { transform: translateY(-4px); }
.tile .thumb { position: relative; }
.tile .thumb::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(0, 0, 0, .28));
  opacity: 0; transition: opacity .18s ease;
  pointer-events: none;
}
.tile:hover .thumb::after { opacity: 1; }

/* THE FOOTER IS WHERE A STUDIO SIGNS ITS NAME. */
.bottom { position: relative; }
.bottom::before {
  content: "";
  position: absolute; left: 0; right: 0; top: 0; height: 2px;
  background: var(--seam);
  -webkit-mask: radial-gradient(circle 7px at 34px 50%, transparent 98%, #000 100%);
  mask: radial-gradient(circle 7px at 34px 50%, transparent 98%, #000 100%);
  opacity: .6;
}

@media (prefers-reduced-motion: reduce) {
  .tile, .logo .mark, .logo .mark::after { transition: none; }
  .tile:hover { transform: none; }
  .logo:hover .mark::after { transform: rotate(20deg); }
}

.hero .kickline { display: flex; align-items: center; flex-wrap: wrap; gap: 0 2px; }
