/* Atlis: dark stage, real text over a fixed WebGL canvas. Type lives in the block below the @font-face rules. */

/* Work Sans Bold: the word "atlis" wherever it stands as the name (intro, hero, share image). It is the face of
   the logo's own lettering, so these match the header logo, which is the same letters as outlines. */
@font-face {
  font-family: 'Work Sans';
  src: url('assets/fonts/work-sans-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
/* Inter: headings, body and labels. */
@font-face {
  font-family: 'Inter';
  src: url('assets/fonts/inter-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('assets/fonts/inter-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('assets/fonts/inter-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* -------------------------------------------------------------------- type --
   Every type decision lives here. Swapping a face is this block plus the @font-face rules above.
   --font-display is the wordmark (header, hero, intro, fallback); --font-heading is the h2s. */
:root {
  --font-display: 'Work Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-heading: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-text: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --text-weight: 400;
  --wordmark-weight: 700;
  --wordmark-tracking: 0.02em; /* 2 percent, as in the logo, at every size */
  --wordmark-case: lowercase;
  --heading-weight: 700;
  --heading-tracking: -0.03em; /* Inter wants tighter tracking at heading sizes */
  --heading-leading: 1.05;
  --eyebrow-weight: 600;
  --eyebrow-size: 0.74rem;
  --eyebrow-tracking: 0.14em;
  --eyebrow-case: uppercase;
  --eyebrow-color: rgba(184, 240, 255, 0.75); /* the hero block's cyan, held back */
  --label-size: 0.84rem; /* scroll cue, footer, captions: sentence case, normal tracking */
  --nav-size: 0.875rem; /* the header link: about 14px, sentence case, grey */
  --body-leading: 1.55;
  --body-measure: 32rem;
  --lead-size: clamp(1.25rem, 0.7vw + 1.05rem, 1.7rem); /* "Catch what you can carry.", between heading and body */
  --founder-name-size: 1.0625rem;
  --founder-role-size: 0.9rem;
  --content-title-size: clamp(2.2rem, 3vw + 0.8rem, 4.1rem); /* the Games page heading */
  --content-text-size: clamp(1.0625rem, 0.3vw + 0.98rem, 1.25rem); /* same as story body */
  --tile-number-size: clamp(2.25rem, 1.6vw + 1.6rem, 3.1rem);
}

:root {
  --bg: #02050f;
  --ink: #edf0f8;
  --ink-2: #a7afc3;
  --ink-3: #8089a4;
  --block: #8ff4ff; /* COLORS.block in src/config.js */
  --T: 1000vh; /* total scroll length; section spans in index.html add up to 1 */
  --gutter: clamp(1.25rem, 5.5vw, 6rem);
  --blk: min(17lvh, 36vw); /* hero block size: matches HERO in src/stage.js */
  --blk-y: 40lvh;
  --p: 0;
  color-scheme: dark;
}
@media (max-aspect-ratio: 9/10) {
  :root { --blk-y: 36lvh; }
}

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

html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100%;
  /* Transparent on purpose: a solid body background paints over the fixed stage gradient (body::before).
     The base colour comes from html. */
  background: transparent;
  color: var(--ink);
  font-family: var(--font-text);
  font-weight: var(--text-weight);
  line-height: var(--body-leading);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

/* The stage gradient (same as the WebGL background), so pre-load and fallback match the scene. */
body::before {
  content: '';
  position: fixed;
  inset: 0 0 auto 0;
  height: 100lvh;
  z-index: -1;
  background:
    radial-gradient(120% 90% at 85% 110%, #0a1535 0%, rgba(10, 21, 53, 0) 60%),
    linear-gradient(170deg, #010206 0%, #030a1c 60%, #08122e 100%);
}

h1, h2, p { margin: 0; }
[tabindex='-1']:focus { outline: none; } /* headings focused after a jump are not controls */

/* ------------------------------------------------------------------ canvas -- */

#gl {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100vh;
  height: 100lvh;
  display: block;
  z-index: 0;
  opacity: 0;
  transition: opacity 0.6s ease;
  pointer-events: none;
}
.gl-ready #gl { opacity: 1; }
/* Hand-over from the CSS block to the WebGL block (intro skipped): an instant swap in one frame, with the
   WebGL pendulum started at the CSS block's angle, so the two never show side by side. */
.gl-swap #gl, .gl-swap .fallback { transition: none; }
.no-gl #gl { display: none; }

/* ---------------------------------------------------------------- fallback -- */

.fallback {
  position: fixed;
  inset: 0 0 auto 0;
  height: 100lvh;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.7s ease;
}
.no-js .fallback,
html:not(.js) .fallback,
.no-gl .fallback,
.js:not(.intro):not(.gl-ready) .fallback,
.intro.intro-done:not(.gl-ready) .fallback {
  opacity: 1;
}

.fb-rig {
  position: absolute;
  left: calc(50% - var(--blk) / 2);
  top: calc(var(--blk-y) - var(--blk) / 2);
  width: var(--blk);
  height: var(--blk);
  transform-origin: 50% calc(var(--blk) * -5.44); /* the pivot, far above the top of the screen */
  animation: fb-swing 1.9s ease-in-out infinite alternate;
  opacity: clamp(0, calc(1 - (var(--p) - 0.06) * 25), 1);
}
.fb-string {
  position: absolute;
  left: calc(50% - 0.75px);
  bottom: calc(100% + var(--blk) * 0.09);
  width: 1.5px;
  height: calc(var(--blk) * 5.6);
  background: #a4a9ba;
  box-shadow: 0 0 6px rgba(184, 240, 255, 0.35);
}
.fb-cap {
  position: absolute;
  left: 32%;
  width: 36%;
  bottom: 100%;
  height: 9%;
  background: #3b3fa8;
  border-radius: 3px 3px 1px 1px;
}
.fb-block {
  position: absolute;
  inset: 0;
  border-radius: 7%;
  background: radial-gradient(120% 120% at 35% 25%, #c8fcff 0%, var(--block) 55%, #7fdcf0 100%);
  box-shadow:
    0 0 calc(var(--blk) * 0.12) rgba(143, 244, 255, 0.5),
    0 0 calc(var(--blk) * 0.45) rgba(80, 200, 255, 0.2);
}
.fb-glow {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(28% 36% at 70% 52%, rgba(74, 92, 255, 0.22), transparent 70%),
    radial-gradient(18% 24% at 76% 46%, rgba(255, 59, 74, 0.12), transparent 70%),
    radial-gradient(16% 20% at 64% 60%, rgba(43, 255, 90, 0.08), transparent 70%);
  opacity: clamp(0, calc((var(--p) - 0.2) * 8), 1);
}
@media (max-aspect-ratio: 9/10) {
  .fb-glow { background:
    radial-gradient(50% 26% at 50% 30%, rgba(74, 92, 255, 0.22), transparent 70%),
    radial-gradient(30% 16% at 60% 26%, rgba(255, 59, 74, 0.12), transparent 70%); }
}
/* Without JavaScript nothing fades or pins, so the page is plain flow: each chapter one screen tall, and the
   block lives in the hero screen only (it scrolls away with the hero copy instead of riding over the rest). */
html:not(.js) .fallback {
  position: absolute;
  height: 100svh;
}
html:not(.js) .ch {
  height: auto;
  min-height: 100svh;
  margin-top: 0;
}
html:not(.js) .frame {
  position: relative;
  height: auto;
  min-height: 100svh;
}
html:not(.js) .frame--side,
html:not(.js) .frame--finale {
  padding-top: 5rem;
  padding-bottom: 5rem;
}
html:not(.js) .ch-finale .frame { padding-bottom: 6rem; }
/* The bar scrolls away with the page: without the script there is no band to keep text from running under it. */
html:not(.js) .site-header { position: absolute; }
@keyframes fb-swing {
  from { transform: rotate(-2.6deg); }
  to { transform: rotate(2.6deg); }
}

/* ------------------------------------------------------------------- intro -- */

.intro-word {
  position: fixed;
  inset: 0 0 auto 0;
  height: 100svh;
  z-index: 2;
  display: none;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.intro .intro-word { display: flex; }
.intro-word__in {
  display: flex;
  padding-left: var(--wordmark-tracking);
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 9vw, 8.5rem);
  font-weight: var(--wordmark-weight);
  letter-spacing: var(--wordmark-tracking);
  text-transform: var(--wordmark-case);
  line-height: 1;
  color: #070c22;
  /* Dark letters caught by a thin blue-violet rim light, as in the reference. */
  text-shadow:
    0.012em 0.014em 0 #5d5cf0,
    0.022em 0.026em 0.01em rgba(110, 120, 255, 0.55),
    -0.006em -0.006em 0 rgba(60, 70, 160, 0.35),
    0 0 0.35em rgba(70, 80, 255, 0.16);
  animation: intro-in 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) 0.15s both;
}
.intro-word span { display: inline-block; will-change: transform; }
@keyframes intro-in {
  from { opacity: 0; transform: scale(0.985); }
  to { opacity: 1; transform: none; }
}

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

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: max(1.15rem, env(safe-area-inset-top)) var(--gutter) 0.85rem;
  pointer-events: none;
  transition: opacity 0.9s ease 0.1s;
}
.intro:not(.intro-done) .site-header { opacity: 0; }
.brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--ink);
  text-decoration: none;
  pointer-events: auto;
  border-radius: 4px;
}
.brand-mark { width: 1.6rem; height: 1.6rem; display: block; flex: none; }
/* The logo: the shapes with the lowercase word, as one drawing (the word is outlines, not a font). Its height is
   the height the shapes alone had, so the header keeps its rhythm. Source: atlis/brand/logo/ in the OS. */
.brand-logo { height: 1.6rem; width: auto; display: block; flex: none; color: var(--ink); overflow: visible; }
.brand-name {
  font-family: var(--font-display);
  font-weight: var(--wordmark-weight);
  font-size: 0.82rem;
  letter-spacing: calc(var(--wordmark-tracking) * 0.86);
  text-transform: var(--wordmark-case);
  margin-right: calc(var(--wordmark-tracking) * -0.86);
}
/* One link, where the "First game in development" label was. */
.site-nav {
  display: flex;
  margin-right: -0.4rem; /* the link's own padding: its text lines up with the gutter */
  pointer-events: auto;
  transition: opacity 0.25s ease; /* faded while the beam passes behind it (app.js) */
}
.site-nav a {
  padding: 0.55rem 0.4rem;
  border-radius: 6px;
  font-size: var(--nav-size);
  color: var(--ink-3);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.2s ease;
}
.site-nav a:hover, .site-nav a[aria-current] { color: var(--ink); }
.brand:focus-visible, .site-nav a:focus-visible, .text-link:focus-visible {
  outline: 2px solid var(--block);
  outline-offset: 2px;
}
/* While the block's string hangs behind the bar (app.js), a tight halo in the stage colour round the word, so
   the string passes behind it instead of through it (the CSS block's string too, before WebGL is ready). */
.site-nav.over-string a,
html:not(.gl-ready) .site-nav a {
  text-shadow: 0 0 2px var(--bg), 0 0 3px var(--bg), 0 0 5px var(--bg), 0 0 9px rgba(2, 5, 15, 0.9);
}
.intro:not(.intro-done) .site-header * { pointer-events: none !important; }

/* The Games page: its content scrolls under the bar, so a band of the stage colour fades in behind it once the
   page has moved (src/site.js). The home page never needs it. */
.site-header::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--bg);
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  opacity: 0;
  transition: opacity 0.3s ease;
}
.site-header.is-over-content::before { opacity: 1; }

/* The fade between pages, and the brand link's cut to the top: the stage colour over the page (not the bar). */
.cut {
  position: fixed;
  inset: 0;
  z-index: 4;
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
}
.cut.is-on, .arriving .cut { opacity: 1; }
.arriving .cut { transition: none; }

/* --------------------------------------------------------- touch target ---- */

.block-hit {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 4;
  border-radius: 18%;
  touch-action: none; /* dragging the block never scrolls the page; anywhere else scrolls normally */
  cursor: grab;
  -webkit-tap-highlight-color: transparent;
}
.block-hit[hidden] { display: none; }
.block-hit.is-dragging { cursor: grabbing; }

/* ---------------------------------------------------------------- chapters -- */

main { position: relative; z-index: 3; }

/* Each chapter is a tall section with a sticky, screen-sized frame. Sections overlap by one screen,
   so a frame is pinned for exactly its share of the scroll: p in [start, start + span]. */
.ch {
  position: relative;
  height: calc(var(--span) * var(--T) + 100svh);
  margin-top: -100svh;
  pointer-events: none;
}
.ch:first-child { margin-top: 0; }
.frame {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
}
.copy, .hero-copy, .site-footer { pointer-events: auto; }

/* Text sits over a dark stage; a soft shadow keeps it clean when a piece drifts behind. */
.hero-copy, .copy, .site-footer { text-shadow: 0 0 1.5rem rgba(2, 5, 15, 0.85); }

.js [data-reveal] { will-change: opacity, transform; }
.js [data-reveal]:not([data-reveal='hero']):not([data-reveal='finale']):not([data-reveal='footer']) { opacity: 0; }

/* Hero */
.hero-copy {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  top: calc(var(--blk-y) + var(--blk) / 2 + clamp(1.75rem, 6vh, 3.5rem));
  text-align: center;
}
.intro:not(.intro-done) .hero-copy { opacity: 0; }
/* The slow fade is for the intro reveal only; afterwards scroll drives the opacity directly, with no lag. */
.intro:not(.intro-ended) .hero-copy { transition: opacity 0.9s ease; }
.wordmark {
  font-family: var(--font-display);
  font-weight: var(--wordmark-weight);
  font-size: clamp(2.5rem, 5.4vw, 4.4rem); /* lowercase needs more size than the old capitals to carry the same weight */
  letter-spacing: var(--wordmark-tracking);
  margin-right: calc(var(--wordmark-tracking) * -1);
  text-transform: var(--wordmark-case);
  line-height: 1;
}
.lede {
  margin-top: 0.85rem;
  color: var(--ink-2);
  font-size: clamp(1.02rem, 0.3vw + 0.95rem, 1.2rem);
  letter-spacing: 0;
}
/* The scroll cue: a small outlined track with a tiny copy of the block dropping down it (it was the word
   "Scroll" until 2026-11-14). */
.scroll-cue {
  position: absolute;
  left: 0;
  right: 0;
  bottom: max(1.6rem, env(safe-area-inset-bottom));
  display: flex;
  justify-content: center;
  line-height: 0;
  transition: opacity 0.7s ease;
}
.scroll-cue__track {
  position: relative;
  width: 1.3rem;
  height: 2.1rem;
  border: 1.5px solid rgba(128, 137, 164, 0.7); /* --ink-3, a little quieter */
  border-radius: 0.65rem;
}
.scroll-cue__dot {
  position: absolute;
  left: 50%;
  top: 0.4rem;
  width: 0.34rem;
  height: 0.34rem;
  margin-left: -0.17rem;
  border-radius: 28%;
  background: var(--block);
  box-shadow: 0 0 0.45rem rgba(143, 244, 255, 0.75);
  /* Three drops, then it rests at the top: an endless CSS animation keeps the compositor producing frames at
     the display's full rate (about 4 points of a core on its own, measured), even while the scene idles at 30. */
  animation: cue 2.2s cubic-bezier(0.45, 0, 0.3, 1) 1s 3;
}
.intro:not(.intro-done) .scroll-cue { opacity: 0; }
.scroll-cue.is-hidden { opacity: 0; transition-duration: 0.25s; }
.scroll-cue.is-hidden .scroll-cue__dot,
.intro:not(.intro-done) .scroll-cue__dot { animation: none; } /* the drops start once the cue is on screen */
@keyframes cue {
  0% { transform: translateY(0); opacity: 1; }
  55% { transform: translateY(0.85rem); opacity: 0; }
  56% { transform: translateY(0); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}

/* Middle chapters: text in a left column, the formation to the right. */
.frame--side {
  display: flex;
  align-items: center;
  padding: 0 var(--gutter);
}
.copy { max-width: min(34rem, 40vw); }
.eyebrow {
  font-family: var(--font-text);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: var(--eyebrow-case);
  color: var(--eyebrow-color);
}
h2 {
  margin: 1rem 0 1.25rem;
  font-family: var(--font-heading);
  font-weight: var(--heading-weight);
  font-size: clamp(2rem, 3.6vw + 0.5rem, 4.1rem); /* about 60px at 1440 */
  line-height: var(--heading-leading);
  letter-spacing: var(--heading-tracking);
  text-wrap: balance;
}
/* The game's lead line, between its heading and body. */
.lead-line {
  margin: -0.35rem 0 0.9rem;
  color: var(--ink);
  font-size: var(--lead-size);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.more { margin-top: 1.25rem; font-size: 0.9375rem; }
.text-link {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid rgba(167, 175, 195, 0.35);
  padding-bottom: 1px;
  border-radius: 2px;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.text-link:hover { color: var(--ink); border-color: var(--ink-2); }

/* The founders, under the cloud beat's body: two quiet credits, each a small glowing shape from the mark. */
.founders {
  width: fit-content;
  max-width: 100%;
  list-style: none;
  margin: 1.6rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem 2.2rem;
}
.founder { display: flex; align-items: center; gap: 0.85rem; }
.founder__name, .founder__role { display: block; line-height: 1.3; }
.founder__name { font-size: var(--founder-name-size); font-weight: 600; color: var(--ink); }
.founder__role { font-size: var(--founder-role-size); color: var(--ink-3); }
.founder__role { display: none; } /* "Co-founder" is hidden for now (2026-11-14): delete this one line to bring it back */
/* Each founder's Roblox avatar headshot (a transparent image, saved in assets/founders/) on a tile in one of the
   mark's colours and shapes: the violet rounded square for Beckham, the orange circle for Braxton, the blue
   triangle for Breck (the bare shape as a placeholder until his headshot is supplied). */
.avatar {
  flex: none;
  display: block;
  width: 3.25rem;
  height: 3.25rem;
  overflow: hidden;
}
.avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
.avatar--square {
  border-radius: 24%;
  background: radial-gradient(120% 120% at 30% 18%, #bdb4ff 0%, #9a8dff 52%, #7b6aee 100%);
  box-shadow: 0 0 0.9rem rgba(154, 141, 255, 0.45), 0 0 0.2rem rgba(154, 141, 255, 0.7);
}
.avatar--circle {
  border-radius: 50%;
  background: radial-gradient(120% 120% at 30% 18%, #ffd596 0%, #ffb347 52%, #f29a22 100%);
  box-shadow: 0 0 0.9rem rgba(255, 179, 71, 0.42), 0 0 0.2rem rgba(255, 179, 71, 0.7);
}
.avatar--triangle { overflow: visible; } /* the glow is a drop shadow that follows the triangle */
.avatar--triangle svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  filter: drop-shadow(0 0 0.42rem rgba(134, 187, 251, 0.5)) drop-shadow(0 0 0.1rem rgba(134, 187, 251, 0.7));
}

.body {
  color: var(--ink-2);
  font-size: clamp(1.0625rem, 0.3vw + 0.98rem, 1.25rem); /* 17px minimum on desktop */
  line-height: var(--body-leading);
  max-width: var(--body-measure);
  text-wrap: pretty;
}

/* Finale: centred under the mark, footer at the bottom of the screen. */
.frame--finale {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: 0 var(--gutter) calc(max(1.4rem, env(safe-area-inset-bottom)) + 4.2rem);
}
.copy > h2:first-child { margin-top: 0; } /* no label above the heading any more */
.copy--center { text-align: center; max-width: 40rem; }
.copy--center .body { margin: 0 auto; text-wrap: balance; } /* no single word left on the last line */
.copy--center h2 { margin-top: 0; }
.site-footer {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: max(1.4rem, env(safe-area-inset-bottom));
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: var(--label-size);
  color: var(--ink-3);
}
/* Two items: the copyright at the left, the address at the right. ("A Treehous company" was dropped on
   2026-11-13: the copyright line already names Treehous.) */
.site-footer p:last-child { text-align: right; }
.site-footer a {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid rgba(167, 175, 195, 0.35);
  padding-bottom: 1px;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.site-footer a:hover { color: var(--ink); border-color: var(--ink-2); }
/* "Treehous LLC" in the copyright line links to Treehous's site. It reads as plain text until it is hovered or
   focused, then turns Treehous's green (#4cb695, the "hous" of its wordmark). No underline. */
.site-footer a.footer-treehous { color: inherit; border-bottom: 0; padding-bottom: 0; }
.site-footer a.footer-treehous:hover, .site-footer a.footer-treehous:focus-visible { color: #4cb695; }
.site-footer p { margin: 0; }
/* Narrow screens: the two do not fit side by side, so they stack, centred. */
@media (max-width: 640px) {
  .site-footer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    text-align: center;
  }
  .site-footer p:nth-child(n) { text-align: center; }
}
.site-footer a:focus-visible {
  outline: 2px solid var(--block);
  outline-offset: 4px;
  border-radius: 2px;
}

/* Portrait: formation in the upper part, text in the lower part. */
@media (max-aspect-ratio: 9/10) {
  .frame--side {
    align-items: flex-end;
    padding-bottom: calc(max(1.25rem, env(safe-area-inset-bottom)) + 6svh);
  }
  .copy { max-width: 36rem; }
  h2 { font-size: clamp(1.85rem, 6.4vw, 3.3rem); margin: 0.8rem 0 1rem; }
  .frame--finale { padding-bottom: calc(max(1.25rem, env(safe-area-inset-bottom)) + 4.4rem); }
}
@media (max-aspect-ratio: 9/10) and (max-width: 420px) {
  .body { font-size: 1rem; line-height: 1.58; } /* 16px on phones */
}

/* Short landscape screens (phones on their side). */
@media (max-height: 520px) and (min-aspect-ratio: 9/10) {
  h2 { font-size: clamp(1.45rem, 6.6vh, 2.3rem); margin: 0.6rem 0 0.75rem; }
  .eyebrow { font-size: 0.66rem; }
  .body { font-size: 1rem; line-height: 1.5; } /* 16px on phones held sideways */
  .copy { max-width: min(26rem, 39vw); }
  .site-header { padding-top: max(0.8rem, env(safe-area-inset-top)); }
  .frame--finale { padding-bottom: 3.2rem; }
  .site-footer { bottom: 0.9rem; }
  .wordmark { font-size: 1.7rem; }
  .hero-copy { top: calc(var(--blk-y) + var(--blk) / 2 + 1.1rem); }
}

/* ---------------------------------------------------------- reduced motion -- */

@media (prefers-reduced-motion: reduce) {
  .fb-rig, .scroll-cue__dot { animation: none; }
  .intro-word { display: none !important; }
  * { scroll-behavior: auto; }
}

/* ------------------------------------------------- Open Graph capture mode -- */

.og-word { display: none; }
.og .site-header, .og main, .og .cut, .og .scroll-cue, .og .block-hit { display: none; }
.og .og-word {
  display: block;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 13%;
  z-index: 3;
  text-align: center;
  font-family: var(--font-display);
  font-weight: var(--wordmark-weight);
  font-size: 4rem;
  letter-spacing: var(--wordmark-tracking);
  margin-right: calc(var(--wordmark-tracking) * -1);
  text-transform: var(--wordmark-case);
  color: var(--ink);
}

/* The stacked footer (see .site-footer) is three lines, four on the narrowest phones: keep the finale text clear
   of it. (v1 had two items here, so these were 5.2rem and 6.6rem.) */
@media (max-width: 720px) {
  .frame--finale { padding-bottom: calc(max(1.25rem, env(safe-area-inset-bottom)) + 6.6rem); }
}
@media (max-width: 360px) and (max-aspect-ratio: 9/10) {
  .frame--finale { padding-bottom: calc(max(1.25rem, env(safe-area-inset-bottom)) + 8rem); }
}

/* ------------------------------------------------------------- Games page -- */
/* The scene is held at the truck behind the page (src/main.js). Wide screens: content in a left column, the truck
   a living illustration on the right, dimmed. Portrait: content covers the scene, over a dark backing. Without
   WebGL or JavaScript it is a plain dark page with the same content. */

[data-page='games'] .fallback { display: none; }
.content {
  position: relative;
  z-index: 1;
  padding: clamp(6.5rem, 17vh, 10rem) var(--gutter) clamp(4rem, 10vh, 6rem);
}
.content__in { max-width: min(40rem, 46vw); }
.content__title {
  margin: 0 0 1.1rem;
  font-family: var(--font-heading);
  font-weight: var(--heading-weight);
  font-size: var(--content-title-size);
  line-height: var(--heading-leading);
  letter-spacing: var(--heading-tracking);
}
.content__text {
  color: var(--ink-2);
  font-size: var(--content-text-size);
  line-height: var(--body-leading);
  text-wrap: pretty;
}
.content__title, .content .lead-line, .content__text, .content__quiet, .caption { text-shadow: 0 0 1.5rem rgba(2, 5, 15, 0.85); }
.content .lead-line { margin-top: 0; }
.caption {
  margin-top: 0.75rem;
  color: var(--ink-3);
  font-size: var(--label-size);
}
.content__quiet {
  margin-top: 2.4rem;
  color: var(--ink-3);
  font-size: 1rem;
}

/* In-game shots: one wide frame and a row of three. Sizes are fixed by aspect-ratio, so nothing shifts as they load. */
.gallery { margin-top: 2rem; display: grid; gap: 0.75rem; }
.shot-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.75rem; }
.shot {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(7, 11, 28, 0.82);
}
.shot--main { aspect-ratio: 2 / 1; }

/* Placeholder tiles for the numbers: framed, deliberate, empty, each with a line of glow in a piece colour on top. */
.tile {
  --edge: 255, 59, 74;
  position: relative;
  overflow: hidden;
  background: rgba(7, 11, 28, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.tile::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: rgba(var(--edge), 0.55);
  box-shadow: 0 0 0.7rem rgba(var(--edge), 0.45);
}

.tiles {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
}
.tile { border-radius: 18px; padding: 1.3rem 1.2rem 1.25rem; }
.tile::before { height: 2px; background: rgb(var(--edge)); box-shadow: 0 0 0.75rem 0.05rem rgb(var(--edge)); opacity: 0.95; }
.tile:nth-child(2) { --edge: 74, 92, 255; }
.tile:nth-child(3) { --edge: 255, 227, 42; }
.tile__n {
  display: block;
  color: var(--ink-3);
  font-size: var(--tile-number-size);
  font-weight: 700;
  line-height: 1;
}

/* The footer row in normal flow at the bottom of the Games page (on the home page it sits in the finale frame). */
.site-footer--flow {
  position: relative;
  left: auto;
  right: auto;
  bottom: auto;
  z-index: 1;
  padding: 1.5rem var(--gutter) max(1.4rem, env(safe-area-inset-bottom));
}

/* Portrait: content covers the scene, full width. The section carries a dark backing that fades in at its top
   edge, so text never sits on the truck's glow. */
@media (max-aspect-ratio: 9/10) {
  .content__in { max-width: 40rem; }
  .content {
    background: linear-gradient(to bottom, rgba(2, 5, 15, 0) 0, rgba(2, 5, 15, 0.8) 6.5rem, rgba(2, 5, 15, 0.8) 100%);
  }
  .site-footer--flow { background: rgba(2, 5, 15, 0.8); }
}
@media (max-width: 560px) {
  .content__text { font-size: 1rem; line-height: 1.58; } /* 16px on phones */
  .tile { padding: 1.1rem 1rem 1.05rem; }
}
/* Short landscape screens (phones on their side). */
@media (max-height: 520px) and (min-aspect-ratio: 9/10) {
  .content { padding-top: 5rem; padding-bottom: 3rem; }
  .content__in { max-width: min(30rem, 52vw); }
  .content__title { font-size: clamp(1.6rem, 7vh, 2.3rem); }
  .content__text { font-size: 1rem; line-height: 1.5; }
  .lead-line { font-size: 1.1rem; margin-bottom: 0.6rem; }
  .founders { margin-top: 0.8rem; }
}

/* Narrow phones: slightly smaller avatar tiles, so two founders sit side by side and the third wraps under them. */
@media (max-width: 420px) {
  .avatar { width: 2.75rem; height: 2.75rem; }
  .founders { gap: 0.6rem 1.3rem; }
  .founder { gap: 0.65rem; }
}
