/*
 * voidware.com
 *
 * Two palettes live here on purpose.
 *
 * The studio chrome — header, hero furniture, About, CTA, footer — is cool and
 * metallic, to agree with the Strand mark, which is a brushed silver ribbon.
 * The games are not. Each story section and each card carries its own genre
 * accent via [data-theme], so vivid game worlds sit inside a neutral frame
 * rather than fighting it.
 */

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

:root {
  /* studio ground, coolest to warmest */
  --ink:        #0a0c11;
  --ink-raise:  #12151d;
  --ink-panel:  #171b25;
  --rule:       rgba(200, 208, 220, 0.14);
  --rule-firm:  rgba(200, 208, 220, 0.28);

  --paper:      #eef1f6;
  --paper-mid:  #b8c0cd;
  --paper-dim:  #838d9d;

  --steel:      #c8d0dc;

  /* the mark is brushed metal; the wordmark uses the same sweep */
  --metal: linear-gradient(155deg,
      #ffffff 0%, #ccd4e0 26%, #8d97a6 48%,
      #f2f5f9 68%, #a8b2c1 88%, #dde3ec 100%);

  /* genre accent, overridden per section by [data-theme] */
  --accent:     var(--steel);
  --accent-ink: #0a0c11;
  --tint:       transparent;

  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;
  --s8: 4.5rem;
  --s9: 7rem;

  --t-hero:  clamp(2.4rem, 6.4vw, 5rem);
  --t-h2:    clamp(1.75rem, 4vw, 2.9rem);
  --t-h3:    clamp(1.2rem, 2.2vw, 1.55rem);
  --t-lead:  clamp(1.05rem, 1.6vw, 1.3rem);
  --t-body:  clamp(1rem, 1.1vw, 1.09rem);
  --t-small: 0.875rem;
  --t-micro: 0.75rem;

  --radius:    14px;
  --radius-sm: 8px;
  --radius-pill: 999px;

  --shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
  --shadow-sm: 0 6px 18px rgba(0, 0, 0, 0.4);

  --fast: 140ms;
  --slow: 420ms;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  --gutter: clamp(1.1rem, 4vw, 3rem);
  --measure: 62ch;
  --header-h: 62px;

  --font-ui:      'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* Display only — one weight, no optical-size axis. Never below ~20px. */
  --font-display: 'Instrument Serif', Georgia, 'Times New Roman', serif;
}

/* Genre palettes, carried over from the per-game themes of the old site.
   Scoped to a subtree, not <body>, so several can coexist on one page. */
[data-theme='fantasy'] { --accent: #bf5af2; --accent-ink: #14061f; --tint: #1a0f2e; }
[data-theme='crime']   { --accent: #e8603c; --accent-ink: #1a0503; --tint: #140705; }
[data-theme='scifi']   { --accent: #04d9ff; --accent-ink: #001318; --tint: #020a14; }
[data-theme='retro']   { --accent: #ffd60a; --accent-ink: #201a00; --tint: #171614; }
/* Non-game products get their own accents, taken from the hardware each one
   recreates: 'vfd' is the green of the vacuum fluorescent display in RetroFX,
   'lcd' the amber of the C and AC keys on the JL-120, which has a plain LCD. */
[data-theme='vfd']     { --accent: #7bf7b0; --accent-ink: #04170d; --tint: #0b1410; }
[data-theme='lcd']     { --accent: #f0b93c; --accent-ink: #1c1300; --tint: #14110a; }

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

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-ui);
  font-size: var(--t-body);
  /* 400, not 300: light weights optically thin out on a near-black ground */
  font-weight: 400;
  line-height: 1.65;
  overflow-x: hidden;
  font-synthesis: none;
}

/* Instrument Serif is a display face: one weight, drawn for large sizes. It
   takes the big editorial headings; anything under about 20px would go thin
   and characterless in it, so those are set in Inter instead. Asking for a
   bold it does not have would only get a synthesised one, so h1/h2 are 400. */
h1, h2 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.06;
  margin: 0;
  letter-spacing: 0;
}

h3, h4 {
  font-family: var(--font-ui);
  font-weight: 600;
  line-height: 1.25;
  margin: 0;
  letter-spacing: -0.012em;
}

p { margin: 0 0 var(--s4); }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

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

button { font: inherit; color: inherit; }

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

.wrap {
  width: min(1220px, 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap-narrow {
  width: min(860px, 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  top: var(--s3);
  left: var(--s3);
  z-index: 200;
  padding: var(--s2) var(--s4);
  background: var(--paper);
  color: var(--ink);
  border-radius: var(--radius-sm);
  transform: translateY(-160%);
  transition: transform var(--fast) var(--ease);
}
.skip-link:focus { transform: none; }

/* section furniture */

.section { padding-block: var(--s9); position: relative; }

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4);
  margin-bottom: var(--s6);
}

.section-title { font-size: var(--t-h2); }

.eyebrow {
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--paper-dim);
  margin: 0 0 var(--s3);
}

.lead {
  font-size: var(--t-lead);
  color: var(--paper-mid);
  max-width: var(--measure);
}

/* The display face is a single 400 weight, so a heading no longer separates
   itself from the paragraph under it by weight alone. Give it some air. */
.section-title + .lead,
.section-title + .prose,
.section-title + .qa { margin-top: var(--s4); }

/* ---------------------------------------------------------------- brand - */

/* The paint goes on the <svg>, not on `.mark path`. <use> clones the symbol
   into a shadow tree that a descendant selector cannot reach, so `.mark path`
   matched nothing and the mark drew as default black on a black header. fill
   and stroke are inherited properties, so setting them on the host does cross
   into the clone. */
.mark {
  width: 34px; height: 34px;
  flex: none;
  display: block;
  fill: url(#metalGrad);
  stroke: rgba(0, 0, 0, 0.55);
  stroke-width: 6;
}

.wordmark {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--paper);
  white-space: nowrap;
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
  .wordmark {
    background: var(--metal);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.brand-lockup {
  display: flex;
  align-items: center;
  gap: var(--s3);
  text-decoration: none;
}

.brand-sub {
  font-size: var(--t-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--paper-dim);
  display: block;
  margin-top: 2px;
}

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

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(10, 12, 17, 0.72);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border-bottom: 1px solid var(--rule);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  gap: var(--s5);
  min-height: var(--header-h);
}

.site-nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--s5);
}

.site-nav a {
  text-decoration: none;
  font-size: var(--t-small);
  color: var(--paper-mid);
  transition: color var(--fast) var(--ease);
}
.site-nav a:hover { color: var(--paper); }

.nav-toggle {
  display: none;
  margin-left: auto;
  width: 42px; height: 42px;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--rule-firm);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.nav-toggle svg { width: 20px; height: 20px; }

/* full-screen menu, mobile only */
.nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--ink);
  display: none;
  flex-direction: column;
  padding: var(--s5) var(--gutter) var(--s8);
}
.nav-overlay[data-open='true'] { display: flex; }

.nav-overlay-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--header-h);
}

.nav-overlay nav {
  display: flex;
  flex-direction: column;
  gap: var(--s5);
  margin-top: var(--s7);
}
.nav-overlay nav a {
  text-decoration: none;
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 8vw, 2.4rem);
}

.icon-btn {
  width: 42px; height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--rule-firm);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn:hover { border-color: var(--paper); }

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

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: 0.72em 1.5em;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-ui);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--fast) var(--ease),
              background var(--fast) var(--ease),
              border-color var(--fast) var(--ease),
              color var(--fast) var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn svg { width: 1.05em; height: 1.05em; flex: none; }

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
}
.btn-primary:hover { filter: brightness(1.08); }

.btn-ghost {
  border-color: var(--rule-firm);
  color: var(--paper);
  background: rgba(255, 255, 255, 0.02);
}
.btn-ghost:hover { border-color: var(--paper); background: rgba(255, 255, 255, 0.06); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: center;
}

/* store row — brand colours, deliberately outside the theme system */
.store-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}

.store-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: 0.55em 1.05em;
  border-radius: var(--radius-sm);
  font-size: var(--t-small);
  font-weight: 600;
  text-decoration: none;
  color: #fff;
  transition: transform var(--fast) var(--ease), filter var(--fast) var(--ease);
}
.store-btn:hover { transform: translateY(-1px); filter: brightness(1.12); }
.store-btn svg { width: 1.05em; height: 1.05em; }

.store-btn.steam    { background: linear-gradient(135deg, #1b2838, #66c0f4); }
.store-btn.itch     { background: #fa5c5c; }
.store-btn.play     { background: #00a844; }
.store-btn.appstore { background: #3d3d44; }

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

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  align-items: end;
  overflow: hidden;
  isolation: isolate;
}

.hero-media { position: absolute; inset: 0; z-index: -2; }

.hero-media img,
.hero-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* An optional looping video sits over the still. It stays transparent until
   site.js sees it actually playing, so an unsupported format or a blocked
   autoplay leaves the image showing rather than a black box. It never takes
   pointer events, so the invisible case cannot swallow a click either. */
.hero-loop {
  opacity: 0;
  pointer-events: none;
  transition: opacity 900ms ease;
}

.hero-loop.is-live { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .hero-loop { display: none; }
}

.hero-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, var(--ink) 2%, rgba(10, 12, 17, 0.55) 42%, rgba(10, 12, 17, 0.25) 70%),
    linear-gradient(to right, rgba(10, 12, 17, 0.82) 0%, rgba(10, 12, 17, 0.15) 62%);
}

.hero-inner { padding-block: var(--s8) var(--s9); }

.hero-studio {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-bottom: var(--s5);
}

.hero-title {
  font-size: var(--t-hero);
  max-width: 15ch;
  text-wrap: balance;
}

.hero-subtitle {
  font-family: var(--font-display);
  /* floor raised to 20px: below that the single 400 weight goes thin on dark */
  font-size: clamp(1.25rem, 2.4vw, 1.7rem);
  color: var(--paper-mid);
  font-style: italic;
  margin-top: var(--s2);
}

.hero-tagline {
  font-size: var(--t-lead);
  color: var(--paper-mid);
  max-width: 46ch;
  margin: var(--s4) 0 var(--s6);
}

.hero-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-bottom: var(--s5);
}

.hero-scroll {
  position: absolute;
  bottom: var(--s5);
  left: 50%;
  transform: translateX(-50%);
  color: var(--paper-dim);
  font-size: var(--t-micro);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s2);
  pointer-events: none;
}
.hero-scroll span { animation: nudge 2.6s var(--ease) infinite; }

@keyframes nudge {
  0%, 100% { transform: translateY(0); opacity: 0.55; }
  50%      { transform: translateY(5px); opacity: 1; }
}

/* ----------------------------------------------------------------- pills - */

.pill {
  display: inline-flex;
  align-items: center;
  padding: 0.28em 0.8em;
  border-radius: var(--radius-pill);
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 1px solid var(--rule-firm);
  color: var(--paper-mid);
  background: rgba(255, 255, 255, 0.03);
}

.pill-accent {
  border-color: transparent;
  background: var(--accent);
  color: var(--accent-ink);
}

.pill-genre {
  border-color: transparent;
  background: none;
  padding-inline: 0;
  color: var(--paper-dim);
  letter-spacing: 0.06em;
  text-transform: none;
  font-weight: 400;
}

/* ---------------------------------------------------------------- story - */

.story {
  padding-block: var(--s9);
  background:
    radial-gradient(120% 70% at 80% 0%, var(--tint) 0%, transparent 62%);
  border-top: 1px solid var(--rule);
}

.story-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

.story-beats > * + * { margin-top: var(--s9); }

.beat { max-width: 46ch; }
.beat-heading {
  font-size: var(--t-h3);
  margin-bottom: var(--s3);
}
.beat-heading::before {
  content: '';
  display: block;
  width: 2.2rem;
  height: 3px;
  background: var(--accent);
  margin-bottom: var(--s4);
  border-radius: 2px;
}
.beat p { color: var(--paper-mid); }

/* art column: one stacked image per beat, cross-faded on scroll */
.story-art {
  position: sticky;
  top: calc(var(--header-h) + var(--s5));
  /* Every child is absolutely positioned, so this box has no intrinsic size:
     it has to be told to fill its grid column. Do not use margin-inline:auto
     here — that opts the item out of stretching and collapses it to nothing. */
  width: 100%;
  aspect-ratio: 3 / 2;
  max-height: 74vh;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  border: 1px solid var(--rule);
  /* it is a <button>: strip the UA chrome, keep it looking like a picture */
  display: block;
  padding: 0;
  background: none;
  cursor: pointer;
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.story-art:hover { border-color: var(--accent); }

/* Tells you the picture is a door, without printing a label over the art
   permanently. Hidden from assistive tech — the button has an aria-label. */
.story-art::after {
  content: 'About this game';
  position: absolute;
  right: var(--s3);
  bottom: var(--s3);
  z-index: 2;
  padding: 0.4em 1em;
  border-radius: var(--radius-pill);
  border: 1px solid var(--rule-firm);
  background: rgba(10, 12, 17, 0.78);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-family: var(--font-ui);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--paper);
  opacity: 0;
  transform: translateY(5px);
  transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease);
  pointer-events: none;
}
.story-art:hover::after,
.story-art:focus-visible::after { opacity: 1; transform: none; }

.story-art figure { position: absolute; inset: 0; margin: 0; }
.story-art img {
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.04);
  transition: opacity var(--slow) var(--ease), transform 1.4s var(--ease);
}
.story-art figure[data-active='true'] img { opacity: 1; transform: none; }

/* the mobile equivalent: art inline above each beat */
.beat-art { display: none; }

.story-cta { margin-top: var(--s6); }

/* Story sections alternate sides so the page does not read as a list.
   Driven by a flag from site.js rather than :nth-of-type, which would count
   every <section> on the page, not just the story ones. */
.story[data-flip='true'] .story-grid {
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
}
.story[data-flip='true'] .story-art { order: -1; }

/* ------------------------------------------------------------- projects - */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-bottom: var(--s6);
}

.chip {
  padding: 0.45em 1.05em;
  border-radius: var(--radius-pill);
  border: 1px solid var(--rule-firm);
  background: none;
  color: var(--paper-mid);
  font-size: var(--t-small);
  cursor: pointer;
  transition: all var(--fast) var(--ease);
}
.chip:hover { color: var(--paper); border-color: var(--paper-dim); }
.chip[aria-pressed='true'] {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--ink);
  font-weight: 600;
}

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

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  text-align: left;
  /* catalogue cards are <button>s built by site.js, but a product card is a
     plain <a>, and without this every line inside it draws underlined */
  text-decoration: none;
  color: inherit;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--ink-raise);
  overflow: hidden;
  cursor: pointer;
  transition: transform var(--fast) var(--ease),
              border-color var(--fast) var(--ease),
              box-shadow var(--fast) var(--ease);
}
.card:hover {
  transform: translateY(-3px);
  border-color: var(--accent);
  box-shadow: var(--shadow-sm);
}

.card-media { position: relative; aspect-ratio: 4 / 3; background: #05070a; }
.card-media img { width: 100%; height: 100%; object-fit: cover; }

/* Boxed classics keep their printed border rather than being cropped. */
.card[data-fit='contain'] .card-media { background: #dfe4ec; }
.card[data-fit='contain'] .card-media img { object-fit: contain; }

/* Product key art is a wide banner, not a 4:3 cover. Cropping it to the tile
   would cut the title off one end and the product off the other, and fitting
   it inside leaves deep empty bands, so the tile takes the art's own shape. */
.card[data-fit='free'] .card-media { aspect-ratio: auto; background: #0d1017; }
.card[data-fit='free'] .card-media img { height: auto; object-fit: contain; }

/* Bottom-left, not top: nearly every cover has its title set across the top,
   and a flag up there lands straight on it. */
.card-flag {
  position: absolute;
  bottom: var(--s3);
  left: var(--s3);
  backdrop-filter: blur(6px);
  background: rgba(10, 12, 17, 0.78);
  border-color: rgba(200, 208, 220, 0.4);
  color: var(--paper);
}

/* "Free" keeps the solid accent chip. This needs the compound selector: on
   .pill-accent alone the rule above wins on source order and leaves the dark
   --accent-ink text sitting on the dark flag background, which is unreadable. */
.card-flag.pill-accent {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: transparent;
  backdrop-filter: none;
}

.card-body {
  padding: var(--s4) var(--s4) var(--s5);
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  flex: 1;
}

.card-title {
  font-size: 1.06rem;
  line-height: 1.25;
}
.card-series {
  font-size: var(--t-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}
.card-tagline {
  font-size: var(--t-small);
  color: var(--paper-mid);
  margin: 0;
  flex: 1;
}
.card-foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
  margin-top: var(--s2);
}

.grid-empty {
  grid-column: 1 / -1;
  padding: var(--s8) 0;
  text-align: center;
  color: var(--paper-dim);
}

/* ---------------------------------------------------------------- about - */

.about { border-top: 1px solid var(--rule); }

.about-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(1.5rem, 4vw, 3.5rem);
  margin-top: var(--s6);
}

.about-col h3 {
  font-size: var(--t-h3);
  margin-bottom: var(--s3);
}
.about-col h3::after {
  content: '';
  display: block;
  width: 100%;
  height: 1px;
  background: var(--rule-firm);
  margin-top: var(--s4);
}
.about-col p { color: var(--paper-mid); font-size: var(--t-small); line-height: 1.75; }

.note {
  margin-top: var(--s8);
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--steel);
  border-radius: var(--radius-sm);
  background: var(--ink-raise);
  max-width: var(--measure);
}
.note h3 { font-size: 1.05rem; margin-bottom: var(--s2); }
.note p { color: var(--paper-mid); font-size: var(--t-small); }

/* ------------------------------------------------------------------ cta - */

.cta {
  border-top: 1px solid var(--rule);
  text-align: center;
  background: radial-gradient(90% 120% at 50% 100%, rgba(200, 208, 220, 0.08), transparent 68%);
}
.cta .lead { margin-inline: auto; }
.cta .btn-row { justify-content: center; margin-top: var(--s6); }

.cta-discord {
  background: #5865f2;
  color: #fff;
  font-size: var(--t-body);
  padding: 0.9em 2em;
}
.cta-discord:hover { filter: brightness(1.1); }

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

.site-footer {
  border-top: 1px solid var(--rule);
  padding-block: var(--s6);
  font-size: var(--t-small);
  color: var(--paper-dim);
}
.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
  align-items: center;
  justify-content: space-between;
}
.footer-links { display: flex; flex-wrap: wrap; gap: var(--s5); }
.footer-links a { text-decoration: none; }
.footer-links a:hover { color: var(--paper); }

/* ---------------------------------------------------------------- modal - */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  background: rgba(4, 5, 8, 0.82);
  backdrop-filter: blur(6px);
}
.overlay[data-open='true'] { display: block; }

.modal {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: clamp(0px, 4vh, 3rem) var(--gutter) var(--s8);
}

.modal-panel {
  width: min(880px, 100%);
  margin-inline: auto;
  background: var(--ink-panel);
  border: 1px solid var(--rule-firm);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  position: relative;
}

/* Fixed, not in flow: it sits over the artwork instead of claiming a row of
   its own above it, and stays reachable however far the panel is scrolled. */
.modal-close {
  position: fixed;
  top: var(--s4);
  right: var(--s4);
  z-index: 120;
  background: rgba(10, 12, 17, 0.72);
  border-color: rgba(238, 241, 246, 0.45);
  color: var(--paper);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.modal-close:hover { background: rgba(10, 12, 17, 0.92); border-color: var(--paper); }

/* The banner takes each game's own aspect ratio, written in by site.js once
   the image reports its natural size. The catalogue is a genuine mix — 4:3
   covers, 16:9 renders, 1.85:1 banners and 2.05:1 Magnetic Scrolls posters —
   so any single fixed ratio would crop some titles and letterbox others.
   Matching the art means no crop and no wasted space either way.

   The value below is only the placeholder used before the image loads. Where
   max-height does clamp a tall ratio, a blurred copy of the same image fills
   the remainder rather than leaving bars. */
.modal-hero {
  position: relative;
  aspect-ratio: 16 / 9;
  max-height: 70vh;
  background: #05070a;
  overflow: hidden;
}
.modal-hero img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.modal-hero .hero-fill {
  object-fit: cover;
  filter: blur(30px) saturate(130%);
  transform: scale(1.18);
  opacity: 0.5;
}
.modal-hero .hero-plate { object-fit: contain; }

.modal-body { padding: var(--s6) clamp(1.25rem, 4vw, 3rem) var(--s7); }
.modal-title { font-size: var(--t-h2); }
.modal-tagline { font-size: var(--t-lead); color: var(--paper-mid); margin-top: var(--s2); }
.modal-meta { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s4) 0 var(--s6); }
.modal-prose { max-width: var(--measure); }
.modal-prose p { color: var(--paper-mid); }
.modal-prose em { color: var(--paper); font-style: italic; }

.modal-features {
  margin: var(--s6) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--s2);
  max-width: var(--measure);
}
.modal-features li {
  padding-left: 1.5em;
  position: relative;
  color: var(--paper-mid);
  font-size: var(--t-small);
}
.modal-features li::before {
  content: '';
  position: absolute;
  left: 0.25em; top: 0.62em;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.modal-note {
  margin-top: var(--s6);
  font-size: var(--t-micro);
  line-height: 1.7;
  color: var(--paper-dim);
  max-width: var(--measure);
}

.modal-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;   /* stop buttons stretching to the panel width */
  gap: var(--s4);
  margin-top: var(--s7);
  padding-top: var(--s6);
  border-top: 1px solid var(--rule);
}

/* ------------------------------------------------------------- gallery - */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--s3);
  margin-top: var(--s7);
}

.gallery-item {
  margin: 0;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #05070a;
  border: 0;
  padding: 0;
  cursor: zoom-in;
}
.gallery-item img,
.gallery-item video { width: 100%; height: 100%; object-fit: cover; }
.gallery-item img { transition: transform var(--slow) var(--ease); }
.gallery-item:hover img { transform: scale(1.05); }

.gallery-video {
  grid-column: 1 / -1;
  aspect-ratio: 16 / 9;
  cursor: default;
}

/* ------------------------------------------------------ product pages - */

/* retrofx/ and products/ are static pages that share this stylesheet. Their
   header is the cut-down form — brand, a couple of links, no hamburger — so
   the nav has to stay visible at every width rather than hiding behind a
   toggle that those pages do not have. */
.site-header.subpage .site-nav { display: flex; }

/* Deliberately not .hero. The only RetroFX key art that exists is an 800px
   banner and there is no larger source, so the hero sits it beside the text
   at a size it can actually fill instead of stretching it full-bleed. */
.product-hero {
  padding-block: var(--s8) var(--s7);
  border-bottom: 1px solid var(--rule);
}

.product-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--s7);
  align-items: center;
}

.product-art {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: #0d1017;
  overflow: hidden;
}
.product-art img { display: block; width: 100%; height: auto; }

/* Between .hero-title and a section title: this is the page's h1, but it
   shares the fold with the art rather than owning a whole viewport. */
.product-title { font-size: clamp(2.2rem, 5vw, 3.6rem); margin-bottom: var(--s3); }

.prose { max-width: var(--measure); }
.prose p { color: var(--paper-mid); }
.prose p + p { margin-top: var(--s4); }
.prose a { color: var(--accent); }
.prose em { color: var(--paper); font-style: italic; }

/* FAQ and the differences list: a term with an answer under it. */
.qa { margin: var(--s6) 0 0; max-width: var(--measure); }
.qa dt {
  font-family: var(--font-ui);
  font-weight: 600;
  color: var(--paper);
}
.qa dd {
  margin: var(--s2) 0 var(--s5);
  color: var(--paper-mid);
  font-size: var(--t-small);
}
.qa dd:last-child { margin-bottom: 0; }

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

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 140;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--s5);
  background: rgba(2, 3, 5, 0.94);
}
.lightbox[data-open='true'] { display: flex; }
.lightbox img {
  max-width: 100%;
  max-height: 100%;
  width: auto; height: auto;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.lightbox-close { position: absolute; top: var(--s4); right: var(--s4); }

body[data-locked='true'] { overflow: hidden; }

/* ------------------------------------------------------------ responsive - */

@media (max-width: 900px) {
  .story-grid,
  .story[data-flip='true'] .story-grid { grid-template-columns: 1fr; }
  .story-art { display: none; }

  .beat-art {
    display: block;
    width: 100%;
    margin-bottom: var(--s5);
    border-radius: var(--radius);
    overflow: hidden;
    border: 1px solid var(--rule);
    aspect-ratio: 3 / 2;
    /* also a <button>, opening the same game as the sticky art on desktop */
    padding: 0;
    background: none;
    cursor: pointer;
  }
  .beat-art img { width: 100%; height: 100%; object-fit: cover; }

  .beat { max-width: none; }
  .story-beats > * + * { margin-top: var(--s8); }

  .modal-actions { gap: var(--s4); }

  /* art under the copy, not beside it */
  .product-hero-grid { grid-template-columns: 1fr; gap: var(--s6); }
}

@media (max-width: 760px) {
  .site-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .section { padding-block: var(--s8); }
  .hero-inner { padding-block: var(--s7) var(--s8); }
  .hero-media::after {
    background: linear-gradient(to top, var(--ink) 6%, rgba(10, 12, 17, 0.62) 48%, rgba(10, 12, 17, 0.35) 100%);
  }
  .gallery { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .site-footer .wrap { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 480px) {
  /* the studio line is long and heavily tracked; give it room to fit */
  .hero-studio .eyebrow { letter-spacing: 0.14em; font-size: 0.68rem; }
  .brand-sub { letter-spacing: 0.1em; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .story-art img { opacity: 1; transform: none; }
  .story-art figure:not([data-active='true']) { opacity: 0; }
  .story-art figure[data-active='true'] { opacity: 1; }
}
