/* =========================================================================
   SyphonGames — public stylesheet
   Brand: SyphonDigital house system — ink ground, warm neutrals, one brass accent
   Type:  Instrument Serif (display) / Inter (interface)

   ART DIRECTION NOTE, because it explains most of the decisions below.

   This is a games portal, and the instinct is to make the chrome loud. It does
   the opposite: the frame goes quiet so that THE GAME ART IS THE COLOUR. Twelve
   vivid thumbnails on a warm-black ground read as a curated catalogue; the same
   thumbnails inside cyan gradients and yellow pills read as a link farm.

   So: no gradients as decoration, sharp 2–3px corners instead of pills, a single
   brass accent used sparingly, and the serif reserved for display sizes only —
   interface text stays in Inter, where it is legible at 12px.

   Matches syphondigital.online, which is the parent site.
   ========================================================================= */

/* --------------------------------------------------------------- fonts */
/* Served from /fonts rather than Google Fonts: one less origin to connect to
   before the first paint, which PageSpeed measured at about a second on a slow
   phone. Latin subsets, SIL Open Font License (public/fonts/OFL-*.txt). The
   pages preload the first two with the same ?v=1 URLs; change both together. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter-latin-wght-normal.woff2?v=1") format("woff2");
}
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-serif-latin-400-normal.woff2?v=1") format("woff2");
}
@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/instrument-serif-latin-400-italic.woff2?v=1") format("woff2");
}

/* -------------------------------------------------------------- tokens */
:root {
  /* One accent, three weights. Brass reads as "premium hardware", carries a
     10:1 contrast ratio on the ground, and is the same accent the parent site
     and the Concierge product use. */
  --primary: #d9b477;
  --primary-bright: #f0dcb4;
  --primary-deep: #a9834a;
  --secondary: #0b0a09;

  /* Deliberately NOT a second hue. The old palette had cyan AND yellow fighting
     each other and the game art. Where two states must be distinguished (a NEW
     badge vs a FEATURED one) the difference is brass vs paper, not two colours. */
  --accent: #f4efe7;
  --accent-deep: #cfc7ba;

  /* Surfaces climb away from ink with a faint WARM cast, matching the parent
     site's plaster-and-brass interior rather than the old cool cyan cast. */
  --surface-0: #0b0a09;
  --surface-1: #121010;
  --surface-2: #171513;
  --surface-3: #201c19;
  --line: #2b2622;
  --line-soft: #1c1917;

  /* Contrast on --surface-0, measured: text 19.4:1, muted 7.7:1, dim 5.4:1.
     Every use of --text-dim is small text, so 4.5:1 is the floor. Do not darken. */
  --text: #f4efe7;
  --text-muted: #a9a097;
  --text-dim: #8b847a;

  --font-display: "Instrument Serif", ui-serif, Georgia, "Times New Roman", serif;
  --font-body: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  /* Both of these were referenced further down the old stylesheet but never
     defined, so .strip__title and .ad--test silently fell back to the browser
     default. Defined now. */
  --font-head: var(--font-body);
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Sharp, not soft. Pills belong to the arcade register we moved away from. */
  --radius-sm: 2px;
  --radius: 3px;
  --radius-lg: 4px;
  --radius-pill: 2px;

  --shadow-card: 0 10px 30px -12px rgba(0, 0, 0, .8);
  --shadow-lift: 0 22px 48px -18px rgba(0, 0, 0, .9), 0 0 0 1px rgba(217, 180, 119, .3);

  --ease: cubic-bezier(.16, 1, .3, 1);
  --header-h: 68px;
  --wrap: 1360px;

  /* Safe-area insets, behind variables rather than used inline.
     Two reasons: env() cannot be used inside some shorthand contexts, and
     routing everything through a variable means the whole layout can be tested
     on a desktop by overriding --sat/--sab in devtools — otherwise notch bugs
     are only reproducible on the device that has the notch.
     Paired with viewport-fit=cover in the page <head>; without that, env()
     always resolves to 0 and none of this does anything. */
  --sat: env(safe-area-inset-top, 0px);
  --sar: env(safe-area-inset-right, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);
}

/* -------------------------------------------------------------- reset */
*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; padding: 0; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  min-height: 100vh;
  /* dvh accounts for the retractable mobile address bar; vh above is the
     fallback for browsers without it. Ordering matters — dvh must come second. */
  min-height: 100dvh;
  background: var(--surface-0);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

img, svg, video, canvas, iframe { display: block; max-width: 100%; }

a { color: inherit; text-decoration: none; }

button, input, select, textarea { font: inherit; color: inherit; }

button { background: none; border: 0; cursor: pointer; }

ul, ol { list-style: none; }

/* The serif is a DISPLAY face. It is applied at heading sizes only; anything
   that has to work at 14px or below stays in Inter, which is why .card__title
   and .stage__bar-title below deliberately opt out. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.01em;
}

:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--primary); color: #16120b; }

/* ------------------------------------------------------------ utilities */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  /* The insets matter in landscape on a notched phone, where the notch eats
     into one side and content would otherwise sit under it. */
  padding-left: calc(clamp(16px, 4vw, 32px) + var(--sal));
  padding-right: calc(clamp(16px, 4vw, 32px) + var(--sar));
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: -60px; left: 12px;
  z-index: 200;
  background: var(--accent);
  color: var(--secondary);
  padding: 10px 18px;
  border-radius: var(--radius-sm);
  font-weight: 600;
  transition: top .2s var(--ease);
}
.skip-link:focus { top: 12px; }

.hidden { display: none !important; }

/* --------------------------------------------------------------- header */
/* The brand and search sat under the notch / status bar on real phones. The
   header is sticky at top:0, so its own top edge is the thing that needs the
   inset — padding here rather than a margin, so the blurred background still
   extends up behind the system UI instead of leaving a bare strip. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  padding-top: var(--sat);
  background: rgba(11, 10, 9, .9);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}

.site-header__inner {
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 28px);
}

.brand { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

.brand__mark { width: 34px; height: 34px; }

/* Set in the interface face, uppercase and tracked — the same lockup treatment
   the parent site uses, so the two headers read as one family. */
.brand__text {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 15px;
  letter-spacing: .055em;
  text-transform: uppercase;
  white-space: nowrap;
}
.brand__text em { font-style: normal; font-weight: 600; color: var(--primary); }

/* Search sits in the header because finding a game is the site's core job. */
.header-search {
  position: relative;
  flex: 1;
  max-width: 460px;
}

.header-search__input {
  width: 100%;
  height: 42px;
  padding: 0 44px 0 42px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text);
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.header-search__input::placeholder { color: var(--text-dim); }
.header-search__input:focus {
  border-color: var(--primary-deep);
  background: var(--surface-1);
  outline: none;
}

.header-search__icon {
  position: absolute;
  left: 14px; top: 50%;
  transform: translateY(-50%);
  width: 18px; height: 18px;
  color: var(--text-dim);
  pointer-events: none;
}

.header-search__submit {
  position: absolute;
  right: 5px; top: 5px;
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-sm);
  color: #16120b;
  background: var(--primary);
  transition: background .2s var(--ease);
}
.header-search__submit:hover { background: var(--primary-bright); }

/* Live suggestions under the header search. */
.header-search__results {
  position: absolute;
  top: calc(100% + 8px);
  left: 0; right: 0;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  max-height: 380px;
  overflow-y: auto;
}

.suggest {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--line-soft);
  transition: background .15s var(--ease);
}
.suggest:last-child { border-bottom: 0; }
.suggest:hover, .suggest:focus-visible { background: var(--surface-3); }
.suggest img { width: 56px; height: 32px; object-fit: cover; border-radius: 2px; }
.suggest strong { font-size: 14px; font-weight: 600; }
.suggest span { font-size: 12px; color: var(--text-dim); }
.suggest--empty { padding: 16px; color: var(--text-dim); justify-content: center; }

.nav { display: flex; align-items: center; gap: 4px; margin-left: auto; }

.nav__link {
  position: relative;
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
  transition: color .2s var(--ease);
  white-space: nowrap;
}
.nav__link:hover { color: var(--text); }
.nav__link.is-active { color: var(--text); }

/* A single brass hairline marks the current section — the same datum rule that
   runs around the walls of the 3D studio on the parent site. */
.nav__link.is-active::after {
  content: "";
  position: absolute;
  left: 14px; right: 14px; bottom: 2px;
  height: 1px;
  background: var(--primary);
}

.nav__toggle { display: none; padding: 8px; border-radius: var(--radius-sm); }

/* ------------------------------------------------------- category rail */
.rail {
  border-bottom: 1px solid var(--line-soft);
  background: var(--surface-1);
}

/* The chips wrap onto a second row rather than scrolling off the edge. The rail
   used to scroll horizontally, but with the scrollbar hidden there was nothing
   telling anyone it could — on a mouse, the categories past the fold were simply
   unreachable. Wrapping shows the lot. Below 860px it goes back to a swipe,
   where the gesture is obvious and vertical space is worth more. */
.rail__track {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-block: 10px;
}

@media (max-width: 860px) {
  .rail__track {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
  }
}
.rail__track::-webkit-scrollbar { display: none; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: .04em;
  color: var(--text-muted);
  white-space: nowrap;
  scroll-snap-align: start;
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
.chip:hover {
  color: var(--text);
  border-color: var(--primary-deep);
}
.chip.is-active {
  background: var(--primary);
  border-color: var(--primary);
  color: #16120b;
  font-weight: 600;
}
.chip__count { font-size: 11px; opacity: .6; font-variant-numeric: tabular-nums; }

/* ----------------------------------------------------------------- main */
main { flex: 1; padding-block: clamp(24px, 4vw, 44px); }

.section { margin-bottom: clamp(36px, 5vw, 60px); }

.section__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line-soft);
}

.section__title {
  font-size: clamp(22px, 2.6vw, 30px);
  display: flex;
  align-items: center;
  gap: 12px;
}

/* A short brass rule before section titles. Flat, not a gradient — the parent
   site's hairline motif, borrowed intact. */
.section__title::before {
  content: "";
  width: 22px;
  height: 1px;
  background: var(--primary);
  flex: 0 0 auto;
}

.section__sub { color: var(--text-dim); font-size: 13.5px; margin-top: 4px; }

/* A few sentences at the top of a category, naming what is in it. */
.category-intro { margin: -4px 0 22px; }
.category-intro p { font-size: 15px; line-height: 1.65; margin-bottom: 10px; }
.category-intro p:last-child { margin-bottom: 0; }

.section__link {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--primary);
  white-space: nowrap;
  transition: color .2s var(--ease);
}
.section__link:hover { color: var(--primary-bright); }

/* ----------------------------------------------------------------- hero */
.hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(20px, 3vw, 44px);
  align-items: center;
  padding: clamp(26px, 4vw, 48px);
  margin-bottom: clamp(32px, 4vw, 52px);
  /* Flat. The old version stacked two coloured radial gradients here; against
     a featured game's cover art they simply muddied it. */
  background: var(--surface-1);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  overflow: hidden;
}

/* One brass hairline across the top edge, in place of the glow. */
.hero::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, var(--primary-deep), transparent 62%);
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 18px;
}
.hero__eyebrow::before {
  content: "";
  width: 26px;
  height: 1px;
  background: var(--primary-deep);
}

.hero__title {
  font-size: clamp(34px, 5.4vw, 62px);
  margin-bottom: 16px;
  text-wrap: balance;
}
.hero__title em { font-style: italic; color: var(--primary); }

.hero__text {
  color: var(--text-muted);
  font-size: clamp(15px, 1.3vw, 17px);
  max-width: 48ch;
  margin-bottom: 26px;
}

.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; }

.hero__stats {
  display: flex;
  gap: clamp(18px, 3vw, 34px);
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--line-soft);
}
.hero__stat b {
  display: block;
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 400;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.hero__stat span {
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: .16em;
  text-transform: uppercase;
}

.hero__art { position: relative; }

/* display:block is load-bearing, not decoration. <a> is inline by default, and
   an inline element ignores aspect-ratio, gives the img no height to fill, and
   — because it is the positioned ancestor — hands .hero__card-body a containing
   block derived from its line boxes rather than the card. The body collapses to
   near-zero width and the description wraps one letter per line, running down
   the side of the image. */
.hero__card {
  display: block;
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line);
  box-shadow: var(--shadow-card);
  aspect-ratio: 16 / 10;
  background: var(--surface-2);
}
.hero__card img { display: block; width: 100%; height: 100%; object-fit: cover; }

.hero__card-body {
  position: absolute;
  inset: auto 0 0 0;
  padding: 18px;
  background: linear-gradient(transparent, rgba(11, 10, 9, .95) 62%);
}
.hero__card-body h3 { font-size: 22px; margin-bottom: 4px; }
.hero__card-body p { font-size: 13px; color: var(--text-muted); }

/* --------------------------------------------------------------- buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 44px;
  padding: 0 26px;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: .08em;
  text-transform: uppercase;
  transition: transform .16s var(--ease), background .2s var(--ease),
              color .2s var(--ease), border-color .2s var(--ease);
  border: 1px solid transparent;
}
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--primary); color: #16120b; }
.btn--primary:hover { background: var(--primary-bright); }

/* Paper, not a second hue — the strongest thing available on an ink ground. */
.btn--accent { background: var(--accent); color: var(--secondary); }
.btn--accent:hover { background: #fff; }

.btn--ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--text);
}
.btn--ghost:hover { border-color: var(--primary-deep); color: var(--primary); }

.btn--sm { height: 36px; padding: 0 16px; font-size: 12px; }
.btn--block { width: 100%; }
.btn[disabled] { opacity: .5; pointer-events: none; }

/* ----------------------------------------------------------------- grid */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: clamp(12px, 1.4vw, 18px);
}
.grid--wide { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }

/* The featured grid shows whole rows only: six games used to leave five on
   one row and one on the next. Its column count is set per width here rather
   than by auto-fill (the same 1-5 columns auto-fill gave), so these rules can
   know it: the card that starts an incomplete last row is hidden, and every
   card after it. Never the first row, so a short list still shows. */
#grid-featured { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 535px) and (max-width: 807.98px) {
  #grid-featured { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  #grid-featured > :nth-child(2n+1):not(:first-child):nth-last-child(1) { display: none; }
}
@media (min-width: 808px) and (max-width: 1068.98px) {
  #grid-featured { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  #grid-featured > :nth-child(3n+1):not(:first-child):nth-last-child(-n+2),
  #grid-featured > :nth-child(3n+1):not(:first-child):nth-last-child(-n+2) ~ * { display: none; }
}
@media (min-width: 1069px) and (max-width: 1335.98px) {
  #grid-featured { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  #grid-featured > :nth-child(4n+1):not(:first-child):nth-last-child(-n+3),
  #grid-featured > :nth-child(4n+1):not(:first-child):nth-last-child(-n+3) ~ * { display: none; }
}
@media (min-width: 1336px) {
  #grid-featured { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  #grid-featured > :nth-child(5n+1):not(:first-child):nth-last-child(-n+4),
  #grid-featured > :nth-child(5n+1):not(:first-child):nth-last-child(-n+4) ~ * { display: none; }
}

/* ------------------------------------------------------------ game card */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .22s var(--ease), box-shadow .22s var(--ease), border-color .22s var(--ease);
}
.card:hover, .card:focus-within {
  transform: translateY(-3px);
  border-color: var(--line);
  box-shadow: var(--shadow-lift);
}

.card__media {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--surface-3);
  overflow: hidden;
}

.card__img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .4s var(--ease), filter .3s var(--ease);
}
/* No saturate() boost. The art is already the brightest thing on the page and
   pushing it further just posterises anything already vivid. */
.card:hover .card__img { transform: scale(1.05); }

/* Signature: the intake. The gesture is kept — the card draws the game up on
   hover — but the cyan wash is now a plain ink scrim, so the thumbnail darkens
   evenly instead of being tinted a colour the game never used. */
.card__intake {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(11, 10, 9, .62);
  opacity: 0;
  transition: opacity .25s var(--ease);
}
.card:hover .card__intake, .card:focus-within .card__intake { opacity: 1; }

.card__play {
  width: 50px; height: 50px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--primary);
  color: #16120b;
  transform: scale(.72);
  transition: transform .28s var(--ease);
}
.card:hover .card__play, .card:focus-within .card__play { transform: scale(1); }

.card__badge {
  position: absolute;
  top: 8px; left: 8px;
  padding: 3px 9px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--secondary);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
}
/* Brass vs paper distinguishes the two badge states without a second hue. */
.card__badge--new { background: var(--primary); color: #16120b; }

/* Mode, not promotion. Top-RIGHT so it never collides with the Featured/New
   badge on the left: a game can easily be both, and two pills stacked on the
   same corner is how you get an unreadable thumbnail. Outlined rather than
   filled, so it reads as information about the game rather than a shout. */
.card__mode {
  position: absolute;
  top: 8px; right: 8px;
  padding: 3px 9px;
  border-radius: var(--radius-sm);
  background: rgba(11, 10, 9, .82);
  border: 1px solid var(--accent);
  color: var(--accent);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
}

.card__plays {
  position: absolute;
  bottom: 8px; right: 8px;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  background: rgba(11, 10, 9, .82);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.card__body { padding: 11px 12px 13px; }

/* Interface face on purpose: a serif at 14px in a dense grid of two-line titles
   loses more legibility than it gains in character. */
.card__title {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0;
  margin-bottom: 4px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card__meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--text-dim);
}
.card__cat { color: var(--primary-deep); font-weight: 600; text-transform: uppercase; }

/* Stretched link keeps the whole card clickable without nesting anchors. */
.card__link::after { content: ""; position: absolute; inset: 0; z-index: 1; }

/* --------------------------------------------------------- game skeleton */
.skeleton {
  background: var(--surface-2);
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line-soft);
}
.skeleton__media { aspect-ratio: 16 / 9; }
.skeleton__line { height: 11px; margin: 10px 12px; border-radius: 2px; }
.skeleton__line:last-child { width: 55%; margin-bottom: 14px; }
.skeleton__media, .skeleton__line {
  background: linear-gradient(90deg, var(--surface-3) 25%, #2c2723 50%, var(--surface-3) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s infinite linear;
}
@keyframes shimmer { to { background-position: -200% 0; } }

/* -------------------------------------------------------------- game page */
.player {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 22px;
  align-items: start;
}

.stage {
  position: relative;
  background: var(--surface-0);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 16 / 9;
}
.stage.is-fullscreen { aspect-ratio: auto; height: 100vh; height: 100dvh; }

.stage__frame { width: 100%; height: 100%; border: 0; background: var(--surface-0); }

/* The pre-roll: nothing loads until the player asks for it. Saves bandwidth
   and stops twelve iframes fighting for the CPU on a phone. */
.stage__preroll {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 24px;
  background-size: cover;
  background-position: center;
}
.stage__preroll::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(11, 10, 9, .82);
  backdrop-filter: blur(6px);
}
.stage__preroll > * { position: relative; }
.stage__preroll h1 { font-size: clamp(26px, 3.4vw, 40px); margin-bottom: 10px; }
.stage__preroll p { color: var(--text-muted); margin-bottom: 22px; }

.stage__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0 0 var(--radius) var(--radius);
}
.stage__bar-title { font-family: var(--font-body); font-weight: 600; font-size: 14px; }
.stage__bar-tools { margin-left: auto; display: flex; gap: 6px; }

.icon-btn {
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  transition: background .2s var(--ease), color .2s var(--ease);
}
.icon-btn:hover { background: var(--surface-3); color: var(--primary); }
.icon-btn.is-on { color: var(--primary); }

.panel {
  background: var(--surface-1);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 18px;
}
.panel + .panel { margin-top: 16px; }
.panel h2 { font-size: 19px; margin-bottom: 10px; }
.panel p { color: var(--text-muted); font-size: 14px; }

.dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: 13px; }
.dl dt { color: var(--text-dim); }
.dl dd { text-align: right; font-weight: 500; }

.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.tag {
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid var(--line);
  font-size: 11.5px;
  letter-spacing: .03em;
  color: var(--text-muted);
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.tag:hover { color: var(--primary); border-color: var(--primary-deep); }

/* Rating stars */
.stars { display: flex; gap: 4px; }
.stars button {
  width: 26px; height: 26px;
  color: var(--text-dim);
  transition: color .15s var(--ease), transform .15s var(--ease);
}
.stars button:hover { transform: scale(1.15); }
.stars button.is-lit { color: var(--primary); }
.rating-note { font-size: 12.5px; color: var(--text-dim); margin-top: 8px; }

/* ------------------------------------------------------------- prose page */
.prose { max-width: 74ch; }
.prose h1 { font-size: clamp(32px, 4.6vw, 48px); margin-bottom: 10px; }
.prose h2 { font-size: 25px; margin: 38px 0 10px; }
.prose h3 { font-size: 19px; margin: 24px 0 6px; }
.prose p, .prose li { color: var(--text-muted); margin-bottom: 12px; }
.prose ul { list-style: disc; padding-left: 22px; margin-bottom: 16px; }
.prose ol { list-style: decimal; padding-left: 22px; margin-bottom: 16px; }
.prose li { margin-bottom: 6px; }
/* `:not(.btn)` is load-bearing. `.prose a` has specificity 0-1-1 and beats
   `.btn--primary` at 0-1-0, so a button placed inside prose — which is exactly
   where the contact form button lives — was rendered brass-on-brass and read as
   a blank rectangle. Prose link styling was never meant to apply to buttons. */
.prose a:not(.btn) { color: var(--primary); text-decoration: underline; text-underline-offset: 3px; }
.prose a:not(.btn):hover { color: var(--primary-bright); }
.prose strong { color: var(--text); }
.prose__updated {
  display: inline-block;
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-dim);
  padding: 4px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  margin-bottom: 28px;
}
.prose__lede { font-size: 17px; color: var(--text); margin-bottom: 24px; }

/* ----------------------------------------------------------------- guides */
/* The game guides (/guides/), built by docs/guides/build-guides.js. */
.prose kbd {
  display: inline-block;
  min-width: 1.7em;
  padding: 0 6px;
  font: 600 12px/1.7 var(--font-mono);
  color: var(--text);
  text-align: center;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: var(--radius-sm);
  vertical-align: 1px;
}
/* Breadcrumbs keep their own quiet look inside prose, not the prose link style. */
.prose .crumbs a:not(.btn) { color: inherit; text-decoration: none; }
.prose .crumbs a:not(.btn):hover { color: var(--primary); }
.guide__play { margin-bottom: 24px; }
.guide__shot { margin: 0 0 28px; }
.guide__shot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
}
.guide__shot figcaption { margin-top: 8px; font-size: 12.5px; color: var(--text-dim); }
.prose .guide-list { list-style: none; padding-left: 0; display: grid; gap: 14px; margin: 8px 0 28px; }
.prose .guide-list__item {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 18px;
  align-items: start;
  margin: 0;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
}
.prose .guide-list__item--text { grid-template-columns: 1fr; }
.guide-list__media img { display: block; width: 100%; height: auto; border-radius: var(--radius-sm); }
.prose .guide-list h2 { font-size: 20px; margin: 0 0 6px; }
.prose .guide-list p { margin: 0; font-size: 14.5px; }
.game-guide-link { margin-top: 14px; }
@media (max-width: 600px) {
  .prose .guide-list__item { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------- contact */

/* The contact form. It lives inside .prose, so the rules below are written two
   classes deep where they must outrank `.prose p`. */
.contact-form {
  display: grid;
  gap: 16px;
  margin: 8px 0 12px;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
}
.contact-form fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
.contact-form legend,
.contact-form label { color: var(--text); font-size: 14px; font-weight: 500; }
.contact-form__types { display: flex; flex-wrap: wrap; gap: 8px; }
.contact-form__types legend { width: 100%; margin-bottom: 8px; }
.choice { display: inline-flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.choice input { accent-color: var(--primary); margin-top: 3px; flex: none; }
.contact-form__types .choice {
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-0);
  color: var(--text-muted);
  font-weight: 400;
  transition: border-color .2s var(--ease), color .2s var(--ease);
}
.contact-form__types .choice:has(input:checked) {
  border-color: var(--primary-deep);
  background: rgba(217, 180, 119, .06);
  color: var(--text);
}
.contact-form .choice--check { color: var(--text-muted); font-weight: 400; line-height: 1.5; }

.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
.form-group { display: grid; gap: 16px; }
.form-field { display: grid; align-content: start; gap: 6px; min-width: 0; }
.form-field__opt { margin-left: 4px; color: var(--text-dim); font-size: 12.5px; font-weight: 400; }
.contact-form .form-field__hint { margin: 0; color: var(--text-dim); font-size: 12.5px; }

.form-input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-0);
  color: var(--text);
  font: inherit;
  font-size: 15px;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
textarea.form-input { min-height: 110px; resize: vertical; line-height: 1.5; }
.form-input::placeholder { color: var(--text-dim); }
.form-input:focus { outline: none; border-color: var(--primary-deep); box-shadow: 0 0 0 3px rgba(217, 180, 119, .15); }
.form-input--file { padding: 8px; color: var(--text-muted); font-size: 14px; }
.form-input--file::file-selector-button {
  margin-right: 12px;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-3);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

/* Off screen rather than display:none, which form-filling scripts look for. */
.contact-form__trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

.contact-form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }
.contact-form__progress { display: flex; flex: 1; align-items: center; gap: 12px; min-width: 180px; color: var(--text-muted); font-size: 13px; }
.contact-form__progress[hidden] { display: none; }
.contact-form__bar { flex: 1; height: 4px; border-radius: 2px; background: var(--line); overflow: hidden; }
.contact-form__bar i { display: block; width: 0; height: 100%; background: var(--primary); transition: width .2s linear; }

.contact-form .contact-form__status {
  margin: 0;
  padding: 12px 14px;
  border-left: 2px solid var(--primary-deep);
  background: rgba(217, 180, 119, .06);
  color: var(--text);
  font-size: 14.5px;
}
.contact-form .contact-form__status--error { border-left-color: #d27a6a; background: rgba(210, 122, 106, .08); }
.contact-form .contact-form__status[hidden] { display: none; }

/* With the script running, only the fields for the chosen kind of message
   show. Without it every field shows, and the server sorts it out. */
.contact-form[data-js][data-type="general"] [data-show],
.contact-form[data-js][data-type="problem"] [data-show="game"],
.contact-form[data-js][data-type="game"] [data-show="problem"],
.contact-form[data-js][data-type="game"] [data-hide="game"] { display: none; }

@media (max-width: 620px) {
  .contact-form { padding: 16px; }
}

.notice-block {
  padding: 16px 18px;
  border-left: 2px solid var(--primary-deep);
  background: rgba(217, 180, 119, .05);
  color: var(--text-muted);
  margin-bottom: 28px;
}
.notice-block a { color: var(--primary); text-decoration: underline; text-underline-offset: 3px; }

/* Secondary to the form button, but still comfortably legible — an alternative
   route people cannot read is not an alternative route. */
.contact-alt {
  margin: 18px 0 28px;
  color: var(--text-muted);
  font-size: 14.5px;
}
.contact-alt a {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--primary-deep);
  padding-bottom: 2px;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.contact-alt a:hover { color: var(--primary); border-bottom-color: var(--primary); }

/* ---------------------------------------------------------------- toolbar */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px;
  background: var(--surface-1);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  margin-bottom: 20px;
}
.toolbar__label { font-size: 12px; letter-spacing: .06em; color: var(--text-dim); }
.toolbar__spacer { margin-left: auto; }

.select {
  height: 36px;
  padding: 0 32px 0 12px;
  /* Chevron stroke follows --text-dim; update both together. */
  background: var(--surface-2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b847a' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 8px center / 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  appearance: none;
  cursor: pointer;
  font-size: 13px;
}
.select:focus { border-color: var(--primary-deep); outline: none; }

/* ------------------------------------------------------------ empty state */
.empty {
  text-align: center;
  padding: clamp(40px, 8vw, 80px) 20px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
}
.empty__icon { font-size: 42px; margin-bottom: 12px; opacity: .5; }
.empty h2 { font-size: 24px; margin-bottom: 8px; }
.empty p { color: var(--text-muted); max-width: 44ch; margin: 0 auto 20px; }

/* ------------------------------------------------------------- pagination */
.pager {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  margin-top: 32px;
}
.pager__btn {
  min-width: 38px; height: 38px;
  padding: 0 12px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  transition: color .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
}
.pager__btn:hover:not([disabled]) { border-color: var(--primary-deep); color: var(--primary); }
.pager__btn.is-active {
  background: var(--primary);
  border-color: var(--primary);
  color: #16120b;
}
.pager__btn[disabled] { opacity: .35; pointer-events: none; }

/* ------------------------------------------------------------ breadcrumbs */
.crumbs {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  letter-spacing: .04em;
  color: var(--text-dim);
  margin-bottom: 16px;
}
.crumbs a:hover { color: var(--primary); }
.crumbs span[aria-hidden] { opacity: .5; }

/* ----------------------------------------------------------------- toast */
.toast {
  position: fixed;
  bottom: calc(20px + var(--sab)); left: 50%;
  transform: translate(-50%, 120%);
  z-index: 300;
  padding: 12px 22px;
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-card);
  font-size: 14px;
  font-weight: 500;
  transition: transform .3s var(--ease);
}
.toast.is-up { transform: translate(-50%, 0); }
/* Error is the one place a second hue is justified: "something went wrong" must
   not be sayable in the same colour as "this is interactive". */
.toast--error { border-color: #b4553f; color: #f0b3a3; }
.toast--ok { border-color: var(--primary-deep); }

/* ---------------------------------------------------------------- footer */
.site-footer {
  margin-top: auto;
  /* The extra bottom inset clears the iPhone home indicator, which otherwise
     sits over the copyright line. */
  padding-block: 48px calc(28px + var(--sab));
  background: var(--surface-1);
  border-top: 1px solid var(--line-soft);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: minmax(220px, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: 32px;
  margin-bottom: 32px;
}

.site-footer__about p {
  color: var(--text-dim);
  font-size: 13px;
  max-width: 40ch;
  margin-top: 12px;
}

.site-footer h3 {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 14px;
}

.site-footer li { margin-bottom: 8px; }

.site-footer a {
  font-size: 13px;
  color: var(--text-dim);
  transition: color .2s var(--ease);
}
.site-footer a:hover { color: var(--text); }

/* The submit line sits under the footer blurb and should read as a nudge, not
   as body copy. */
.site-footer__submit { margin-top: 10px; }
.site-footer__submit a { color: var(--primary); font-weight: 500; }
.site-footer__submit a:hover { color: var(--primary-bright); }

.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 22px;
  border-top: 1px solid var(--line-soft);
  font-size: 12px;
  color: var(--text-dim);
}

/* States the relationship out loud. SyphonGames is a SyphonDigital product, and
   the footer is where that belongs — not stamped across the header. */
.site-footer__parent {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.site-footer__parent a { color: var(--text-muted); font-size: inherit; letter-spacing: inherit; }
.site-footer__parent a:hover { color: var(--primary); }

/* ------------------------------------------------------------ responsive */
@media (max-width: 1024px) {
  /* minmax(0, …), not a bare 1fr. A grid track sized `1fr` has an automatic
     minimum of min-content, so it refuses to shrink below the widest thing
     inside it -- and the game column holds a row of game cards. On a 375px
     phone the column came out 1204px wide, the browser zoomed the whole page
     out to about a third to fit it, and the player had to go hunting for a
     Play button rendered at 30%. The desktop rule above always had the
     minmax; this override dropped it. */
  .player { grid-template-columns: minmax(0, 1fr); }
  .site-footer__grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  .hero { grid-template-columns: 1fr; }
  .hero__art { order: -1; }

  /* Closed, the menu is hidden outright rather than slid up. It used to move
     up by 120% of its own height, which is less than the header it hangs
     below, so its last link and the bottom of its panel stayed over the top
     of the screen and covered the top of the header -- by more on a phone
     with a status-bar inset. Hidden, its links also leave the tab order. */
  .nav {
    position: fixed;
    inset: calc(var(--header-h) + var(--sat)) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 8px;
    background: var(--surface-1);
    border-bottom: 1px solid var(--line);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity .2s var(--ease), transform .25s var(--ease), visibility 0s linear .25s;
  }
  .nav.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity .2s var(--ease), transform .25s var(--ease), visibility 0s;
  }
  .nav__link { padding: 12px 14px; }
  .nav__link.is-active::after { left: 14px; right: auto; width: 20px; }
  .nav__toggle { display: grid; place-items: center; margin-left: auto; }
}

@media (max-width: 620px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .brand__text { display: none; }
  .header-search { max-width: none; }
  .site-footer__grid { grid-template-columns: 1fr; gap: 24px; }
  .hero__stats { flex-wrap: wrap; gap: 16px 24px; }
  .stage { aspect-ratio: 4 / 3; }
}

/* ---------------------------------------------------------- preferences */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .card:hover { transform: none; }
  .card:hover .card__img { transform: none; }
}

@media print {
  .site-header, .site-footer, .rail, .stage { display: none; }
  body { background: #fff; color: #000; }
}

/* ------------------------------------------------------------------ *
 * Ads
 *
 * Slots are hidden until main.js decides there is something to put in
 * them, so with advertising switched off they cost the layout nothing.
 * Each one is labelled: an ad a player mistakes for part of the site is
 * a dark pattern, and Google's policies forbid it too.
 * ------------------------------------------------------------------ */

.ad {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--surface-1);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
}

.ad[hidden] { display: none; }

/* The label sits above the unit rather than over it, so it can never be
   mistaken for ad content or obscure a click. */
.ad::before {
  content: 'Advertisement';
  display: block;
  padding: 5px 10px 0;
  font-size: 9.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.ad__inner { padding: 6px 10px 10px; }

/* Above the player and at the top of listings. min-height reserves space so
   the page does not lurch when the unit arrives; it collapses entirely if
   nothing fills it. */
.ad--leaderboard { min-height: 106px; margin-bottom: 20px; }

/* Beside the player, in the column the panels already occupy. */
.ad--rail { min-height: 276px; margin-bottom: 16px; }

/* Between rows of cards. */
.ad--feed { min-height: 106px; margin: 24px 0; }

.ad--test {
  display: grid;
  place-items: center;
  min-height: 106px;
  border-style: dashed;
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 12px;
}
.ad--test.ad--rail { min-height: 276px; }

@media (max-width: 1024px) {
  /* The rail unit stacks under the game on narrow screens, where a 300px
     column does not exist. */
  .ad--rail { min-height: 0; }
}

@media (max-width: 620px) {
  .ad--leaderboard { min-height: 60px; }
}

@media print {
  .ad { display: none !important; }
}

/* ------------------------------------------------------------------ *
 * More-games strip
 *
 * Sits directly under the player. Horizontal, because vertical space
 * under the stage is precious and a row of five reads as "keep going"
 * where a grid reads as "the page continues".
 * ------------------------------------------------------------------ */

.strip { margin-top: 18px; }
.strip[hidden] { display: none; }

.strip__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.strip__title {
  position: relative;
  font-family: var(--font-head);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  padding-left: 32px;
}
/* The same brass rule the section heads use, so this reads as part of the set. */
.strip__title::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 22px;
  height: 1px;
  background: var(--primary);
}

.strip__all {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
}
.strip__all:hover { color: var(--primary); }

.strip__track {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding-bottom: 6px;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
}

/* Cards are built for a grid, where the column sets the width. In a scroller
   nothing does, so they would collapse to their content. */
.strip__track > * {
  flex: 0 0 clamp(148px, 20vw, 190px);
  scroll-snap-align: start;
}

@media (max-width: 620px) {
  .strip__track > * { flex-basis: 140px; }
}

/* Screenshots. The same scrolling shelf as "More games", wider frames, so a
   player can see the game properly before deciding to load it. */
.shots__track {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding-bottom: 6px;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
}
.shots__item {
  flex: 0 0 min(86%, 420px);
  margin: 0;
  scroll-snap-align: start;
}
.shots__link {
  display: block;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line-soft);
  background: var(--surface-0);
}
.shots__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  transition: transform .25s var(--ease);
}
.shots__link:hover .shots__img,
.shots__link:focus-visible .shots__img { transform: scale(1.02); }
.shots__caption {
  margin-top: 6px;
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.45;
}

/* On a desktop all of them fit side by side, so none hide behind a scroll. */
@media (min-width: 900px) {
  .shots__track {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    overflow: visible;
    padding-bottom: 0;
  }
}

/* Both shelves scroll sideways; a light native scrollbar glared on the dark page. */
.strip__track,
.shots__track { color-scheme: dark; }

/* ------------------------------------------------------------ android app */

/* `.btn` sets display, which outranks the browser's own [hidden] rule. The app
   offer stays hidden until main.js has checked it is on an Android browser and
   not inside the app; without this it would show everywhere. */
.btn[hidden] { display: none; }

.app-download {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 22px;
  margin: 28px 0 10px;
}
.app-download__icon { flex: none; width: 64px; height: 64px; }
.app-download__body { flex: 1 1 220px; }
.app-download__body h2 { font-size: 21px; margin: 0 0 2px; }
.app-download__body p { margin: 0; font-size: 13px; color: var(--text-dim); }
.app-download__body .app-download__here { color: var(--primary); }
