/* =========================================================================
   Wallpaper Engine — site styles

   Dark only. This is a deliberate single-theme design, not an omission: the
   product lives on screens and its audience customises desktops, and the app
   itself is dark. Every colour is painted explicitly from a token, so the page
   holds regardless of the visitor's OS preference.

   Colour comes from the brand guide and nowhere else:
     Persian Blue  #003CC1
     Blue Jeans    #43B3FF
     White         #FFFFFF
   Neutrals are blue-biased so they sit in the same family rather than reading
   as generic greys.

   Every component reads tokens. No component defines a colour of its own.
   ========================================================================= */

/* ---------- tokens ---------- */
:root {
  --brand-deep: #003cc1;
  --brand-light: #43b3ff;

  --ground: #080c14;
  --ground-alt: #0b111c;
  --surface: #0e1523;
  --surface-2: #141d2f;
  --line: #1e2a42;
  --line-strong: #2c3b59;

  --text: #e8effa;
  --text-dim: #93a6c4;
  --text-faint: #6b7d9b;

  --accent: #43b3ff;
  --accent-hover: #6ac4ff;
  --accent-ink: #04182e;
  --accent-wash: rgb(67 179 255 / 0.11);
  --accent-line: rgb(67 179 255 / 0.28);

  --good: #3ddc97;
  --good-wash: rgb(61 220 151 / 0.12);
  --warn: #ffb648;
  --warn-wash: rgb(255 182 72 / 0.12);

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4);
  --shadow-md: 0 12px 32px -18px rgb(0 0 0 / 0.85);
  --shadow-lg: 0 40px 80px -40px rgb(0 0 0 / 0.9);

  --radius: 14px;
  --radius-sm: 9px;
  --radius-lg: 22px;

  --shell: 74rem;
  --shell-narrow: 48rem;
  --shell-prose: 42rem;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);

  --font-display: Outfit, ui-sans-serif, system-ui, -apple-system,
    'Segoe UI', Roboto, sans-serif;
  --font-body: Outfit, ui-sans-serif, system-ui, -apple-system,
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace;

  --step-0: clamp(1rem, 0.97rem + 0.15vw, 1.075rem);
  --step-1: clamp(1.15rem, 1.08rem + 0.35vw, 1.35rem);
  --step-2: clamp(1.45rem, 1.3rem + 0.7vw, 1.9rem);
  --step-3: clamp(1.85rem, 1.55rem + 1.4vw, 2.75rem);
  --step-4: clamp(2.4rem, 1.7rem + 3.2vw, 4.5rem);

  color-scheme: dark;
}

/* ---------- fonts ---------- */
/* Outfit, self-hosted. Variable across 300-800, split into two Latin subsets;
   the browser fetches only what a page's characters need, so most pages pull
   the 32 KB latin file alone. Do not add Arboria to a font stack — see
   src/assets/fonts/README.md. */
@font-face {
  font-family: Outfit;
  src: url('/assets/fonts/outfit-latin.woff2') format('woff2');
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Outfit;
  src: url('/assets/fonts/outfit-latin-ext.woff2') format('woff2');
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Locales Outfit cannot serve fall back to system faces deliberately.
   Outfit ships Latin only, so Russian would otherwise get a silent fallback
   that looks unintentional; naming it here makes it a decision. CJK is the
   same call for a different reason — a CJK webfont costs megabytes. */
.script-cyrillic {
  --font-display: ui-sans-serif, system-ui, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-body: var(--font-display);
}

.script-jp {
  --font-display: 'Hiragino Kaku Gothic ProN', 'Yu Gothic', 'Noto Sans JP', Meiryo, sans-serif;
  --font-body: var(--font-display);
}
.script-kr {
  --font-display: 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', sans-serif;
  --font-body: var(--font-display);
}
.script-sc {
  --font-display: 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC', sans-serif;
  --font-body: var(--font-display);
}
.script-tc {
  --font-display: 'PingFang TC', 'Microsoft JhengHei', 'Noto Sans TC', sans-serif;
  --font-body: var(--font-display);
}

/* Greek. Outfit ships no Greek subset, so this is the same deliberate system
   fallback as Cyrillic and CJK above. Ordered Apple, Windows, Android/Linux. */
.script-greek {
  --font-display: ui-sans-serif, system-ui, 'Helvetica Neue', 'Segoe UI', Roboto,
    'Noto Sans', Arial, sans-serif;
  --font-body: var(--font-display);
}

/* Thai. No Outfit coverage, and Thai needs a face with proper vowel and tone
   mark positioning, which a Latin fallback cannot provide. */
.script-thai {
  --font-display: 'SF Thai', 'Thonburi', 'Leelawadee UI', 'Noto Sans Thai', Tahoma, sans-serif;
  --font-body: var(--font-display);
  /* Thai stacks vowels and tone marks above and below the baseline, so it
     clips at Outfit's line-height the way Arabic does. */
  line-height: 1.8;
}

/* Vietnamese is Latin, but Outfit's two subsets stop short of U+1EA0-U+1EF1,
   which is most of the tone-marked vowels (ạ ế ộ ừ ...). Outfit would render
   the unmarked letters and fall back per-glyph for the rest, mixing two faces
   inside single words. A whole-locale system stack is the lesser evil until
   an Outfit Vietnamese subset is added here. */
.script-vietnamese {
  --font-display: ui-sans-serif, system-ui, 'Helvetica Neue', 'Segoe UI', Roboto,
    'Noto Sans', Arial, sans-serif;
  --font-body: var(--font-display);
}

/* Arabic. Outfit has no Arabic coverage and an Arabic webfont is a second
   family to maintain, so this is the same deliberate system fallback as
   Cyrillic and CJK above. The stack is ordered Apple, Windows, Android/Linux. */
.script-arabic {
  --font-display: 'SF Arabic', 'Geeza Pro', 'Segoe UI', Tahoma, 'Noto Sans Arabic',
    'Noto Naskh Arabic', 'Droid Arabic Naskh', sans-serif;
  --font-body: var(--font-display);
  /* Arabic glyphs carry more vertical detail than Latin at the same size and
     read cramped at Outfit's line-height. */
  line-height: 1.75;
}

/* Hebrew. Outfit has no Hebrew coverage, so this is the same deliberate system
   fallback as Arabic and CJK. Ordered Apple, Windows, Android/Linux. */
.script-hebrew {
  --font-display: 'SF Hebrew', 'Arial Hebrew', 'Segoe UI', 'Noto Sans Hebrew',
    'Noto Sans', Arial, sans-serif;
  --font-body: var(--font-display);
}

/* A "forward" arrow has to point the way reading moves, so it mirrors in RTL.
   Scoped to this one glyph: the download, external-link and chevron icons are
   not directional and would be wrong flipped. */
[dir='rtl'] .icon--directional {
  transform: scaleX(-1);
}

/* The layout mirrors on its own: it is built on flex/grid `gap` and logical
   properties, and the only two physical offsets in this file (`.skip-link`,
   `.trailer__mark`) pair `left: 50%` with a -50% translate, which centres
   identically in either direction. Nothing here needs flipping.

   What does need help is bidi. "Wallpaper Engine" is Latin inside an Arabic
   sentence, and the neutral characters around it — punctuation, digits — get
   reordered by the bidi algorithm unless the run is isolated. */
[dir='rtl'] .brand__lockup,
[dir='rtl'] code,
[dir='rtl'] kbd,
[dir='rtl'] .store__name {
  unicode-bidi: isolate;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

img,
video {
  height: auto;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

p {
  margin: 0;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

a {
  color: var(--accent);
  text-decoration-color: var(--accent-line);
  text-underline-offset: 0.18em;
}

a:hover {
  color: var(--accent-hover);
}

button {
  font: inherit;
  color: inherit;
}

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

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

.skip-link {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -110%);
  z-index: 100;
  padding: 0.7rem 1.2rem;
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-weight: 600;
  text-decoration: none;
  transition: transform 0.15s ease;
}

.skip-link:focus {
  transform: translate(-50%, 0);
  color: var(--accent-ink);
}

/* ---------- layout primitives ---------- */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.shell--narrow {
  max-width: var(--shell-narrow);
}

.shell--prose {
  max-width: var(--shell-prose);
}

.section {
  padding-block: clamp(3.5rem, 8vw, 7rem);
}

.section__head {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  margin-bottom: clamp(2rem, 4vw, 3.25rem);
}

.section__head--center {
  align-items: center;
  text-align: center;
}

.section__title {
  font-size: var(--step-3);
}

.section__title--center {
  text-align: center;
  margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem);
}

.section__lede {
  font-size: var(--step-1);
  color: var(--text-dim);
  max-width: 46ch;
  line-height: 1.55;
  text-wrap: pretty;
}

/* A centred lede stands alone in the full shell width rather than sitting in
   a column, so it takes a wider measure. At 46ch a long paragraph became six
   short lines filling barely half the width — a tall narrow block adrift in
   open space. 64ch is still inside the comfortable 45-75ch reading range but
   sits far better under a large centred heading. Short ledes are unaffected;
   they never reach the limit. */
.section__head--center .section__lede {
  max-width: 64ch;
  margin-inline: auto;
  /* Evens out the last line. Without it the buy lede fell 16 words / 3 words,
     leaving a three-word orphan under a full-width line. Only that one is
     affected today; the rest already break evenly. */
  text-wrap: balance;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0.75rem 0.3rem 0.55rem;
  border: 1px solid var(--accent-line);
  border-radius: 999px;
  background: var(--accent-wash);
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  align-self: flex-start;
}

.eyebrow .icon {
  width: 1rem;
  height: 1rem;
}

.eyebrow--onDark {
  border-color: rgb(255 255 255 / 0.25);
  background: rgb(255 255 255 / 0.1);
  color: #ffffff;
}

/* ---------- brand lockup ---------- */
/* The official horizontal SVG: mark plus wordmark, sized by height so the
   3.48:1 aspect ratio is preserved. It carries its own colours (white +
   Blue Jeans, the brand guide's dark-BG treatment) so nothing here tints it.

   Sized against the header row rather than by eye. At 1.85rem it came out
   30px in a 68px row — shorter than the 35px Buy button beside it, so a
   secondary control outweighed the brand. A wide 3.48:1 lockup also reads
   lighter than a solid filled button at equal height, so it needs to be
   clearly taller, not merely equal. */
.brand {
  display: inline-flex;
  align-items: center;
  flex: none;
  text-decoration: none;
}

.brand__lockup {
  width: auto;
  height: 2.5rem;
}

.brand--footer .brand__lockup {
  height: 2.75rem;
}

@media (max-width: 26rem) {
  .brand__lockup {
    height: 2rem;
  }
}

/* ---------- buttons ---------- */
.btn {
  --btn-bg: transparent;
  --btn-fg: var(--text);
  --btn-line: var(--line-strong);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.72rem 1.35rem;
  border: 1px solid var(--btn-line);
  border-radius: 999px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-display);
  font-size: 0.97rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.14s ease, background-color 0.14s ease, border-color 0.14s ease;
}

.btn:hover {
  color: var(--btn-fg);
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0);
}

.btn--primary {
  --btn-bg: var(--accent);
  --btn-fg: var(--accent-ink);
  --btn-line: var(--accent);
}

.btn--primary:hover {
  --btn-bg: var(--accent-hover);
  --btn-line: var(--accent-hover);
}

.btn--secondary {
  --btn-bg: var(--surface-2);
  --btn-fg: var(--text);
  --btn-line: var(--line-strong);
}

.btn--secondary:hover {
  --btn-line: var(--accent);
}

.btn--outline {
  --btn-bg: transparent;
  --btn-fg: var(--accent);
  --btn-line: var(--accent-line);
}

.btn--outline:hover {
  --btn-bg: var(--accent-wash);
  --btn-line: var(--accent);
  --btn-fg: var(--accent-hover);
}

.btn--ghost {
  --btn-bg: rgb(255 255 255 / 0.08);
  --btn-fg: #ffffff;
  --btn-line: rgb(255 255 255 / 0.3);
  backdrop-filter: blur(6px);
}

.btn--ghost:hover {
  --btn-bg: rgb(255 255 255 / 0.16);
  --btn-fg: #ffffff;
}

.btn--sm {
  padding: 0.5rem 1.05rem;
  font-size: 0.9rem;
}

.btn--lg {
  padding: 0.9rem 1.7rem;
  font-size: 1.05rem;
}

/* ---------- header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--ground) 82%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.site-header[data-stuck] {
  border-bottom-color: var(--line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 4.75rem;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-inline-start: auto;
}

.site-nav__links {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.nav-link {
  padding: 0.5rem 0.8rem;
  border-radius: var(--radius-sm);
  color: var(--text-dim);
  font-size: 0.93rem;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}

.nav-link:hover {
  background: var(--surface-2);
  color: var(--text);
}

/* ---------- language picker (<details>, no JS required) ---------- */
.picker {
  position: relative;
}

.picker__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.7rem;
  border-radius: var(--radius-sm);
  color: var(--text-dim);
  font-size: 0.93rem;
  font-weight: 500;
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}

.picker__toggle::-webkit-details-marker {
  display: none;
}

.picker__toggle:hover {
  background: var(--surface-2);
  color: var(--text);
}

.picker__toggle .icon:last-child {
  width: 1rem;
  height: 1rem;
  transition: transform 0.18s ease;
}

.picker[open] .picker__toggle .icon:last-child {
  transform: rotate(180deg);
}

.picker__panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  inset-inline-end: 0;
  z-index: 20;
  min-width: 15rem;
  padding: 0.4rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  /* The list grew past a viewport when the locale count reached the thirties.
     Without these the last entries are simply unreachable. */
  max-block-size: min(70vh, 34rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.lang-list {
  display: grid;
  gap: 1px;
}

/* Two columns once the viewport can afford the wider panel, so the list stays
   scannable instead of turning into a long scroll. */
@media (min-width: 40rem) {
  .picker__panel {
    min-width: 30rem;
  }

  .lang-list {
    grid-template-columns: 1fr 1fr;
    column-gap: 0.25rem;
  }
}

/* Endonym over English name, rather than side by side. Side-by-side pinned the
   English label to the endonym's FIRST baseline, so any name that wrapped
   ("Español (Latinoamérica)") left its English label floating half a row high.
   Stacking makes every row the same shape whatever the name length. */
.lang-item {
  display: grid;
  align-content: center;
  gap: 0.05rem;
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
  font-size: 0.92rem;
  line-height: 1.25;
}

.lang-item:hover {
  background: var(--surface-2);
  color: var(--text);
}

.lang-item.is-current {
  background: var(--accent-wash);
  color: var(--accent);
  font-weight: 600;
}

.lang-english {
  color: var(--text-faint);
  font-size: 0.76rem;
  line-height: 1.2;
}

.lang-item.is-current .lang-english {
  color: inherit;
  opacity: 0.75;
}

/* ---------- mobile menu ---------- */
.mobile-menu {
  display: none;
  margin-inline-start: auto;
}

.mobile-menu__toggle {
  display: inline-flex;
  padding: 0.5rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  list-style: none;
  color: var(--text);
}

.mobile-menu__toggle::-webkit-details-marker {
  display: none;
}

.mobile-menu__close,
.mobile-menu[open] .mobile-menu__open {
  display: none;
}

.mobile-menu[open] .mobile-menu__close {
  display: inline-flex;
}

.mobile-menu__panel {
  position: absolute;
  inset-inline: 0;
  top: 100%;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  max-height: calc(100dvh - 4.75rem);
  overflow-y: auto;
  padding: 1.1rem var(--gutter) 1.6rem;
  border-block: 1px solid var(--line);
  background: var(--ground);
}

.mobile-menu__links {
  display: flex;
  flex-direction: column;
}

.mobile-menu__links .nav-link {
  padding-inline: 0;
  font-size: 1.02rem;
}

.mobile-menu__label {
  margin-top: 0.4rem;
  color: var(--text-faint);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

@media (max-width: 62rem) {
  .site-nav {
    display: none;
  }

  .mobile-menu {
    display: block;
  }

  .site-header__inner {
    position: relative;
  }
}

/* =========================================================================
   HERO — the page's thesis: the surface behind the content is a live
   wallpaper. The canvas is painted by main.js and pauses when off-screen or
   when the tab is hidden, exactly as the product does on a real desktop.
   ========================================================================= */
.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: min(86vh, 46rem);
  padding-block: clamp(4rem, 12vh, 8rem);
  overflow: hidden;
  /* Static stand-in whenever the canvas does not run: reduced motion, no JS,
     or the frames before first paint. */
  background:
    radial-gradient(120% 90% at 18% 12%, #0b4fd8 0%, transparent 58%),
    radial-gradient(95% 85% at 88% 30%, #43b3ff 0%, transparent 52%),
    radial-gradient(120% 120% at 50% 108%, #00164c 0%, transparent 65%),
    linear-gradient(168deg, #002a8f 0%, #041028 78%);
}

.hero--compact {
  min-height: min(52vh, 28rem);
}

.hero__surface {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
}

.hero__veil {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(80% 60% at 50% 45%, rgb(2 8 20 / 0.34) 0%, rgb(2 8 20 / 0.72) 100%),
    linear-gradient(to bottom, transparent 55%, var(--ground) 100%);
}

.hero__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.35rem;
  text-align: center;
  color: #ffffff;
}

/* Mark and wordmark are one lockup, so they sit tighter than the rest of the
   hero's rhythm. The official vertical lockup puts the wordmark at 2.4x the
   mark's width with a gap of 0.28x; the gap here is deliberately tighter. The
   animated asset is cropped to its ink, so these numbers mean what they say. */
.hero__lockup {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
}

.hero__logo {
  width: clamp(6.5rem, 14vw, 9rem);
}

.hero__logo img {
  width: 100%;
  height: auto;
}

.hero__title {
  font-size: var(--step-4);
  letter-spacing: -0.035em;
  text-shadow: 0 2px 30px rgb(0 12 40 / 0.55);
}

/* The h1 must span the hero column. In a centred flex column its width would
   otherwise be shrink-to-fit around the image, while the image sized itself
   from that same width — circular, so the browser falls back to the 300px
   default for a replaced element and the wordmark comes out tiny or not at
   all. Giving the h1 a definite width breaks the loop. */
.hero__title:has(.hero__wordmark) {
  width: 100%;
  line-height: 0;
}

.hero__wordmark {
  /* 2.4x the mark, matching the official vertical lockup. Viewport-relative,
     so it never depends on the parent's content width. */
  width: clamp(15.6rem, 33.6vw, 21.6rem);
  height: auto;
  margin-inline: auto;
  filter: drop-shadow(0 4px 30px rgb(0 12 40 / 0.55));
}

.hero__title--sm {
  font-size: var(--step-3);
}

.hero__lede {
  max-width: 44ch;
  font-size: var(--step-1);
  line-height: 1.5;
  color: rgb(255 255 255 / 0.86);
  text-wrap: pretty;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 0.6rem;
}

.hero__platform {
  margin-top: 0.35rem;
  color: rgb(255 255 255 / 0.6);
  font-size: 0.85rem;
  letter-spacing: 0.03em;
}

/* ---------- capabilities ---------- */
.section--capabilities {
  background: var(--ground);
}

/* Six capabilities. Explicit breakpoints rather than auto-fit, because six
   divides evenly by 1, 2 and 3 but not by 4 or 5 — an auto-fit grid that lands
   on four columns leaves two orphans and an empty cell, which the 1px-gap
   hairline treatment then renders as a visible block. */
.cap-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

@media (min-width: 34rem) {
  .cap-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* An odd count would leave the final card alone in its row, and the 1px-gap
     hairline treatment renders that empty space as a visible block. Letting
     the last card span whatever is left keeps the grid closed at any count. */
  .cap-grid > :last-child:nth-child(2n + 1) {
    grid-column: span 2;
  }
}

@media (min-width: 62rem) {
  .cap-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .cap-grid > :last-child:nth-child(2n + 1) {
    grid-column: auto;
  }

  /* 7, 10, ... land alone; 8, 11, ... leave one gap beside them. */
  .cap-grid > :last-child:nth-child(3n + 1) {
    grid-column: span 3;
  }

  .cap-grid > :last-child:nth-child(3n + 2) {
    grid-column: span 2;
  }

  /* A card three columns wide would otherwise run its body text the full
     width of the grid, far past a readable measure. Lay it out along the row
     with the icon beside the text instead of above it. */
  .cap-grid > .cap:last-child:nth-child(3n + 1) {
    grid-template-columns: auto minmax(0, 62ch);
    grid-template-rows: auto auto;
    justify-content: center;
    column-gap: 1.75rem;
    display: grid;
    align-items: start;
  }

  .cap-grid > .cap:last-child:nth-child(3n + 1) .cap__icon {
    grid-row: span 2;
    margin-bottom: 0;
  }
}



.cap {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: clamp(1.5rem, 3vw, 2.1rem);
  background: var(--ground);
}

.cap__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-bottom: 0.3rem;
  border-radius: var(--radius-sm);
  background: var(--accent-wash);
  border: 1px solid var(--accent-line);
  color: var(--accent);
}

.cap__title {
  font-size: var(--step-1);
  font-weight: 600;
}

.cap__body {
  color: var(--text-dim);
  font-size: 0.97rem;
}

/* ---------- split sections ---------- */
.split {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}

@media (min-width: 60rem) {
  .split {
    grid-template-columns: 1.05fr 1fr;
  }

  .split--reverse .split__copy {
    order: 2;
  }
}

.split__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.1rem;
}

.point-list {
  display: grid;
  gap: 1.35rem 2rem;
  margin-top: 0.4rem;
}

@media (min-width: 34rem) {
  .point-list {
    grid-template-columns: 1fr 1fr;
  }
}

/* Titles run to different line counts per column, and every locale breaks them
   differently, so hard-coding a height would only work for one language. This
   puts each point on the parent's row track instead: all titles share one row
   and all bodies share the next, so the bodies start on the same line whatever
   the title does. Rows are sized by the tallest title, which is what alignment
   requires anyway.

   Guarded by @supports because without subgrid the rule would place each point
   across two rows it does not own. The fallback is the previous behaviour. */
@supports (grid-template-rows: subgrid) {
  .point-list {
    grid-template-rows: auto auto;
  }

  .point {
    display: grid;
    grid-row: span 2;
    grid-template-rows: subgrid;
    gap: 0.3rem;
  }

  /* The gap above now owns the spacing between title and body. */
  .point .point__title {
    margin-bottom: 0;
  }
}

.point__title {
  margin-bottom: 0.3rem;
  font-size: 1rem;
  font-weight: 600;
}

.point__body {
  color: var(--text-dim);
  font-size: 0.93rem;
  line-height: 1.55;
}

.section--editor {
  background: var(--ground-alt);
  border-block: 1px solid var(--line);
}

.screenshot,
.device {
  margin: 0;
}

/* The editor screenshot runs the full shell width — it is a dense 16:9 UI
   capture and needs the room to stay legible. */
.screenshot img {
  width: 100%;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}

.section--editor .screenshot {
  margin-bottom: clamp(2rem, 4vw, 3.25rem);
}

/* The phone renders at its intrinsic 192x412 and is never scaled up. The
   previous version applied a 3D perspective rotation, which looked deliberate
   but stretched the near edge to about 1.1x while squashing the far one, so a
   192px source was being asked for detail it does not have. Flat and sharp
   reads better until there is a higher-resolution render.

   Nothing here is directional, so RTL needs no override: the shadow falls
   straight down and the image mirrors with the grid like any other element. */
.device {
  display: flex;
  justify-content: center;
  padding-block: 2rem;
}

.device img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
  filter: drop-shadow(0 26px 40px rgb(0 0 0 / 0.55));
}

/* ---------- trailer ---------- */
/* Drawn, not photographed. The previous card was a 664px video still scaled
   up ~1.7x, so it softened as screens got bigger; this is a gradient, the
   logomark and two animated rings, which stay sharp at any size and add no
   image request. The rings give the card an obvious affordance — without
   them a flat panel reads as decoration rather than a control. */
.trailer {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: transparent;
  overflow: hidden;
  cursor: pointer;
  box-shadow: var(--shadow-lg);
}

.trailer__art {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(80% 120% at 22% 18%, #0b4fd8 0%, transparent 60%),
    radial-gradient(70% 100% at 84% 82%, #43b3ff 0%, transparent 55%),
    linear-gradient(155deg, #012c93 0%, #050f26 72%);
}

/* The mark sits large and low-contrast so it reads as surface texture rather
   than a second focal point competing with the play control. */
.trailer__mark {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(62%, 22rem);
  height: auto;
  translate: -50% -50%;
  opacity: 0.13;
  filter: blur(0.3px);
  transition: opacity 0.4s ease, scale 0.6s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.trailer:hover .trailer__mark,
.trailer:focus-visible .trailer__mark {
  opacity: 0.2;
  scale: 1.04;
}

.trailer__play {
  position: absolute;
  inset: 50% auto auto 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 5.5rem;
  height: 5.5rem;
}

.trailer__disc {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: 0 10px 40px rgb(0 60 193 / 0.55);
  transition: scale 0.25s ease, background-color 0.25s ease;
}

.trailer__disc .icon {
  width: 2rem;
  height: 2rem;
  margin-inline-start: 0.25rem; /* optical centring of the triangle */
}

.trailer:hover .trailer__disc,
.trailer:focus-visible .trailer__disc {
  scale: 1.08;
  background: var(--accent-hover);
}

/* The aura: two rings expanding out of the disc on a staggered loop. */
.trailer__aura {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--accent);
  opacity: 0;
  animation: trailer-aura 2.8s cubic-bezier(0.2, 0.6, 0.3, 1) infinite;
}

.trailer__aura--2 {
  animation-delay: 1.4s;
}

.trailer:hover .trailer__aura {
  animation-duration: 1.8s;
}

@keyframes trailer-aura {
  0% {
    scale: 1;
    opacity: 0.55;
  }
  70% {
    opacity: 0;
  }
  100% {
    scale: 2.4;
    opacity: 0;
  }
}

.lightbox {
  width: min(96vw, 68rem);
  padding: 0;
  border: none;
  border-radius: var(--radius);
  background: #000000;
  overflow: visible;
}

.lightbox::backdrop {
  background: rgb(2 6 16 / 0.86);
  backdrop-filter: blur(4px);
}

.lightbox__video {
  width: 100%;
  border-radius: var(--radius);
  background: #000000;
}

.lightbox__close {
  position: absolute;
  top: -0.75rem;
  inset-inline-end: -0.75rem;
  display: grid;
  place-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}

.lightbox__close:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* ---------- android band ---------- */
.section--android {
  background: var(--ground-alt);
  border-block: 1px solid var(--line);
}

.point-list--two {
  grid-template-columns: 1fr;
}

@media (min-width: 34rem) {
  .point-list--two {
    grid-template-columns: 1fr 1fr;
  }
}

/* Four points sit below the editor screenshot, so they get the full width. */
@media (min-width: 62rem) {
  .point-list--four {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ---------- buy ---------- */
/* Steam is the primary vendor: it goes first, at full width, with Green Man
   Gaming as a smaller secondary card beneath it. */
.vendors {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
}

.vendor--steam {
  width: 100%;
  max-width: 44rem;
}

.vendor--gmg {
  width: 100%;
  max-width: 26rem;
  padding-block: 1.35rem;
}

.vendor--gmg .vendor__title {
  font-size: 1rem;
  color: var(--text-dim);
  font-weight: 600;
}

.vendor {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: clamp(1.35rem, 3vw, 1.9rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-md);
}

.vendor__title {
  font-size: var(--step-1);
  font-weight: 600;
}

/* Steam card. The logo keeps generous clear space on all sides and renders at
   64px tall; the CTA sits well below it rather than alongside. */
.vendor__cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.75rem;
  padding: 2.5rem 2rem 2rem;
  border-radius: var(--radius);
  background: linear-gradient(160deg, #1b2838 0%, #10161f 100%);
  border: 1px solid #2a3f5a;
  text-decoration: none;
  transition: border-color 0.18s ease, transform 0.18s ease;
}

.vendor__cta:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
}

.vendor__logo img {
  /* 3.28:1 lockup, 64px tall. */
  width: auto;
  height: 4rem;
}

.vendor__action {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.72rem 1.6rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
}

.vendor__cta:hover .vendor__action {
  background: var(--accent-hover);
}

@media (max-width: 30rem) {
  .vendor__cta {
    padding: 1.75rem 1.25rem 1.5rem;
  }

  .vendor__logo img {
    height: 3.25rem;
  }
}

.vendor__fallback {
  margin-top: auto;
  font-size: 0.87rem;
  color: var(--text-faint);
}

.vendor__fallback a {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-weight: 600;
  text-decoration: none;
}

.vendor__fallback a:hover {
  text-decoration: underline;
}

.vendor__link {
  display: block;
  margin-block: auto;
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.vendor__link img {
  width: 100%;
  transition: opacity 0.2s ease;
}

.vendor__link:hover img {
  opacity: 0.82;
}

/* Vendor qualifier, e.g. "Authorized Steam Key Reseller". */
.vendor__note {
  margin-top: -0.4rem;
  color: var(--text-faint);
  font-size: 0.8rem;
  letter-spacing: 0.01em;
}

/* ---------- android store grid ---------- */
.store-grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.store-grid--many {
  grid-template-columns: repeat(auto-fit, minmax(13.5rem, 1fr));
}

.store__link {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  height: 100%;
  padding: 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.store__link:hover {
  border-color: var(--accent);
  color: var(--text);
  transform: translateY(-2px);
}

.store--recommended .store__link {
  border-color: var(--accent-line);
  background: var(--accent-wash);
}

.store__icon {
  color: var(--accent);
  margin-bottom: 0.25rem;
}

.store__title {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
}

.store__body,
.store__note {
  color: var(--text-dim);
  font-size: 0.89rem;
  line-height: 1.5;
}

.store__note {
  color: var(--text-faint);
  font-size: 0.83rem;
}

.badge {
  align-self: flex-start;
  padding: 0.18em 0.6em;
  margin-bottom: 0.3rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.badge--good {
  background: var(--good-wash);
  color: var(--good);
}

.badge--warn {
  background: var(--warn-wash);
  color: var(--warn);
}

.fineprint {
  margin-top: 1.5rem;
  color: var(--text-faint);
  font-size: 0.82rem;
  text-align: center;
}

/* ---------- FAQ ---------- */
.section--faq {
  background: var(--ground-alt);
  border-block: 1px solid var(--line);
}

.accordion {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.qa {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}

.qa[open] {
  border-color: var(--accent-line);
}

.qa__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.05rem 1.35rem;
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.qa__q::-webkit-details-marker {
  display: none;
}

.qa__q:hover {
  color: var(--accent);
}

.qa__q .icon {
  flex: none;
  color: var(--text-faint);
  transition: transform 0.2s ease;
}

.qa[open] .qa__q .icon {
  transform: rotate(180deg);
  color: var(--accent);
}

.qa__a {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  padding: 0 1.35rem 1.35rem;
  color: var(--text-dim);
  font-size: 0.96rem;
}

/* ---------- resources ---------- */
.resource-grid {
  display: grid;
  gap: 1.25rem;
}

@media (min-width: 52rem) {
  .resource-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.resource {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: clamp(1.6rem, 3.5vw, 2.35rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.resource:hover {
  border-color: var(--accent);
  color: var(--text);
  transform: translateY(-2px);
}

.resource__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  margin-bottom: 0.4rem;
  border-radius: var(--radius-sm);
  background: var(--accent-wash);
  border: 1px solid var(--accent-line);
  color: var(--accent);
}

.resource--alt .resource__icon {
  background: color-mix(in srgb, var(--brand-deep) 22%, transparent);
  border-color: color-mix(in srgb, var(--brand-deep) 55%, transparent);
  color: var(--brand-light);
}

.resource__title {
  font-size: var(--step-1);
  font-weight: 600;
}

.resource__body {
  color: var(--text-dim);
  font-size: 0.95rem;
}

/* ---------- prose (legal pages) ---------- */
.prose {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  padding-top: clamp(1rem, 4vw, 2.5rem);
}

.prose h1 {
  font-size: var(--step-3);
  margin-bottom: 0.4rem;
}

.prose h2 {
  font-size: var(--step-2);
  margin-top: 1.6rem;
}

.prose h3,
.prose h4 {
  font-size: var(--step-1);
  margin-top: 1.2rem;
}

.prose p,
.prose li {
  color: var(--text-dim);
  line-height: 1.7;
}

.prose strong {
  color: var(--text);
}

.prose img {
  border-radius: var(--radius-sm);
}

.note {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--accent-line);
  border-inline-start-width: 3px;
  border-radius: var(--radius-sm);
  background: var(--accent-wash);
}

.note--warn {
  border-color: var(--warn);
  background: var(--warn-wash);
}

.note p {
  color: var(--text);
}

/* ---------- footer ---------- */
.site-footer {
  padding-block: clamp(2.5rem, 6vw, 4rem);
  border-top: 1px solid var(--line);
  background: var(--ground-alt);
}

.site-footer__top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.75rem;
  padding-bottom: 1.75rem;
}

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  color: var(--text-faint);
  font-size: 0.87rem;
}

.site-footer__legal {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.site-footer__legal a {
  color: var(--text-dim);
  text-decoration: none;
}

.site-footer__legal a:hover {
  color: var(--accent);
}

/* ---------- motion ---------- */
/* The animated logo is deliberately exempt: it is the brand mark and stays
   for everyone. Only page-driven motion — the hero canvas, transitions,
   smooth scrolling — is suppressed here. */
@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;
  }

  /* The aura stops moving but stays visible as a static halo, so the trailer
     card still reads as a control rather than a flat panel. */
  .trailer__aura {
    opacity: 0.32;
    scale: 1.35;
  }

  .trailer__aura--2 {
    opacity: 0.16;
    scale: 1.75;
  }
}
