/* ==========================================================================
   Magnate — il portale pubblico
   --------------------------------------------------------------------------
   Ereditato dal foglio di Wonderkid (l'intestazione diceva ancora il suo nome
   e «early-access landing page», che qui non descrive niente: la pagina non
   apre nessun accesso anticipato, il gioco è aperto).

   Every colour here is lifted verbatim from the game client's design tokens
   (`app/lib/theme/palette.dart` — option 3a light / 1a dark), so the
   site and the app are literally the same palette rather than a lookalike.

   The recipe, and it is a budget, not a suggestion:
     base      the paper. Nothing else is this colour.
     teal ~30% structure and identity — rules, plates, bars, labels.
     orange 10% the things that MOVE something: the primary action, the age
               number, a decision, a milestone. On chrome it means nothing.
     semantic  green / amber / red on *value*.
   ========================================================================== */

/* ---------- fonts (self-hosted, same files the app bundles) -------------- */

@font-face {
  font-family: 'Space Grotesk';
  src: url('../fonts/SpaceGrotesk-Variable.woff2') format('woff2-variations');
  font-weight: 300 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('../fonts/SpaceGrotesk-LatinExt-Variable.woff2') format('woff2-variations');
  font-weight: 300 700;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Roboto Var';
  src: url('../fonts/Roboto-Normal-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Roboto Var';
  src: url('../fonts/Roboto-LatinExt-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

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

:root {
  /* dark is the default skin, exactly as the app defaults to the device */
  --base: #0f1215;
  --band: #12161a;
  --surface: #161b20;
  --surface-alt: #1d242b;
  --track: #232b32;
  --line: #232b32;
  --line-strong: #313c45;

  --ink: #eef2f4;
  --ink-soft: #b9c4cb;
  --ink-muted: #8c99a3;
  --ink-faint: #6c7a84;

  --accent: #ff6b35;
  --accent-hot: #ff8a5c;
  --accent-deep: #e5551f;
  --on-accent: #190a04;

  --teal: #4e9fb5;
  --teal-deep: #2e6d80;
  --teal-text: #4e9fb5;
  --on-teal: #0f1215;
  --teal-wash: rgba(78, 159, 181, 0.14);

  --good: #3fc97c;
  --money: #4fc98f;
  --warn: #efc93d;
  --bad: #f2635a;
  --violet: #a98be0;
  --pink: #e27a9e;

  --scrim: rgba(6, 9, 11, 0.6);
  --card-shadow: none;
  --sheet-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.6);
  --wash-alpha: 0.16;
  --grain-alpha: 0.035;

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-xl: 28px;
  --r-pill: 999px;

  --shell: min(1220px, 100% - 2 * var(--gutter));
  /* the reading column on content pages — one value, not per-element `ch` */
  --measure: 44rem;
  --gutter: 24px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur: 620ms;

  --display: 'Space Grotesk', 'Segoe UI', system-ui, sans-serif;
  --prose: 'Roboto Var', 'Roboto', system-ui, -apple-system, sans-serif;
}

:root[data-theme='light'] {
  --base: #f7f8f8;
  --band: #ffffff;
  --surface: #ffffff;
  --surface-alt: #f7f8f8;
  --track: #e9edef;
  --line: #e4e8ea;
  --line-strong: #d5dcdf;

  --ink: #16191b;
  --ink-soft: #3b444a;
  --ink-muted: #66727a;
  --ink-faint: #9aa5ac;

  --accent: #f55e1f;
  --accent-hot: #ff6b35;
  --accent-deep: #e5551f;
  --on-accent: #fff4ee;

  --teal: #3a8ca3;
  --teal-deep: #2a6a7d;
  --teal-text: #2a6a7d;
  --on-teal: #ffffff;
  --teal-wash: rgba(58, 140, 163, 0.07);

  --good: #2aa35f;
  --money: #1e9e68;
  --warn: #d9a61e;
  --bad: #d14338;
  --violet: #8e6cc9;
  --pink: #d45b85;

  --scrim: rgba(22, 25, 27, 0.32);
  --card-shadow: 0 1px 2px rgba(22, 25, 27, 0.04);
  --sheet-shadow: 0 20px 60px -10px rgba(22, 25, 27, 0.18);
  --wash-alpha: 0.09;
  --grain-alpha: 0.02;
}

@media (max-width: 720px) {
  :root { --gutter: 18px; }
}

/* ---------- reset -------------------------------------------------------- */

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

/* `hidden` deve vincere su qualunque regola d'autore, ed è il motivo per cui
   c'è un !important in un foglio che altrimenti non ne ha nessuno.
   L'attributo `hidden` funziona grazie a `[hidden] { display: none }` del
   foglio del BROWSER, e le regole d'autore battono quelle del browser a
   prescindere dalla specificità: `.field { display: grid }` ha quindi tenuto
   visibile `#betaExtra`, cioè il campo dell'account Google, anche a spunta
   spenta — che è esattamente il campo in più fra la persona e il pulsante
   che quel `hidden` esisteva per evitare.
   Trovato guardando la pagina in produzione, non l'HTML: nel markup
   l'attributo c'era, e nessuna console diceva niente. Lo stesso difetto è
   vivo sul portale di Wonderkid, da cui questo foglio arriva. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--base);
  color: var(--ink);
  font-family: var(--prose);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  /* the skin swap is instant in the app (BlPalette can't interpolate); here a
     short crossfade is safe because CSS interpolates every token together */
  transition: background-color 260ms var(--ease), color 260ms var(--ease);
}

img, svg { max-width: 100%; display: block; }
button, input { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

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

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

/* ---------- type --------------------------------------------------------- */

.overline {
  font-family: var(--display);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.overline--accent { color: var(--accent); }
.overline--teal { color: var(--teal-text); }

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

.h-display {
  font-size: clamp(3.3rem, 8.2vw, 7.4rem);
  line-height: 0.9;
  letter-spacing: -0.045em;
}
.h-section {
  font-size: clamp(2rem, 5.2vw, 3.6rem);
  letter-spacing: -0.035em;
}
.h-card { font-size: 1.22rem; letter-spacing: -0.02em; }

.lede {
  font-size: clamp(1.02rem, 1.7vw, 1.24rem);
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 56ch;
  margin: 0;
  text-wrap: pretty;
}

.num {
  font-family: var(--display);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

.teal-word { color: var(--teal); }
:root[data-theme='light'] .teal-word { color: var(--teal); }

/* ---------- layout ------------------------------------------------------- */

.shell {
  width: var(--shell);
  margin-inline: auto;
}

section { position: relative; }

.section-pad { padding-block: clamp(80px, 12vh, 150px); }

.rule {
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--line-strong) 18%, var(--line-strong) 82%, transparent);
  border: 0;
  margin: 0;
}

.section-head {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-bottom: clamp(40px, 6vw, 68px);
  max-width: 62ch;
}

/* ---------- ambient: wash, grain, cursor light --------------------------- */

/* The app's one gradient — a soft pool from above the top edge (BlPalette.wash) */
.wash {
  position: fixed;
  inset: -20vh 0 auto 0;
  height: 120vh;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(120vh 90vh at 50% -18%, color-mix(in srgb, var(--teal) calc(var(--wash-alpha) * 100%), transparent), transparent 62%),
    radial-gradient(70vh 60vh at 88% 6%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 60%);
  transition: background 400ms var(--ease);
}

.grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: var(--grain-alpha);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

.spot {
  position: fixed;
  top: 0;
  left: 0;
  width: 620px;
  height: 620px;
  margin: -310px 0 0 -310px;
  border-radius: 50%;
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  background: radial-gradient(circle, color-mix(in srgb, var(--teal) 13%, transparent), transparent 62%);
  transition: opacity 500ms var(--ease);
  will-change: transform;
}
body.pointer-fine .spot { opacity: 1; }

main, header, footer { position: relative; z-index: 3; }

/* ---------- scroll progress + nav ---------------------------------------- */

.progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: 60;
  background: transparent;
}
.progress__bar {
  height: 100%;
  width: 100%;
  transform-origin: 0 50%;
  transform: scaleX(0);
  background: linear-gradient(90deg, var(--accent-deep), var(--accent-hot));
}

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  padding-block: 14px;
  transition: background-color 320ms var(--ease), border-color 320ms var(--ease), backdrop-filter 320ms;
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  background: color-mix(in srgb, var(--band) 82%, transparent);
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  border-bottom-color: var(--line);
}
.nav__inner {
  display: flex;
  align-items: center;
  gap: 18px;
}
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}
.wordmark b { color: var(--ink); font-weight: 700; }
.wordmark i { color: var(--teal); font-style: normal; }

/* The crest carries its own navy fill, so it sits on either skin unchanged.
   Width is pinned as well as height so the row never reflows while the PNG
   is still in flight. */
.wordmark__mark {
  width: 26px;
  height: 26px;
  flex: none;
  object-fit: contain;
  /* The crest's outline is white: on the light skin it would dissolve into
     the page, so a hairline ring gives the silhouette an edge to end on. */
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.28));
}
[data-theme="light"] .wordmark__mark {
  filter: drop-shadow(0 0 0.5px rgba(22, 25, 27, 0.55)) drop-shadow(0 1px 2px rgba(0, 0, 0, 0.16));
}
.wordmark:hover .wordmark__mark { transform: none; }

/* Below 620px the nav is already fighting for room -- the CTA's label was
   being clipped by its own pill even before the crest arrived. The crest is
   the cheaper half of the lockup, so on a phone it carries the brand alone
   and the tracked-out wordmark stands down, which nets the CTA back about
   60px. The name is still announced: `.wordmark` carries an aria-label, so
   hiding the text costs nothing to a screen reader. The footer keeps both --
   it has a whole column to itself. */
@media (max-width: 620px) {
  .wordmark__mark { width: 25px; height: 25px; }
  .nav .wordmark b { display: none; }
}

.nav__links {
  display: flex;
  gap: 6px;
  margin-left: auto;
  align-items: center;
}
.nav__link {
  font-family: var(--display);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 8px 12px;
  border-radius: var(--r-pill);
  transition: color 200ms var(--ease), background-color 200ms var(--ease);
}
.nav__link:hover { color: var(--ink); background: var(--surface-alt); }
.nav__link[aria-current="page"] { color: var(--ink); background: var(--surface-alt); }
@media (max-width: 900px) { .nav__links .nav__link { display: none; } }

/* ---------- the narrow-screen menu --------------------------------------- */
/* Below 900px the row above hides every nav link, and for a long time that
   left a phone with no way to reach /faq/, /odds/ or /devlog/ at all except by
   scrolling to the footer — the header simply had nothing in it. This is the
   replacement.

   A <details> and not a scripted drawer: it opens, closes, takes focus and
   answers the keyboard with no JavaScript at all, which matters because the
   CSP forbids inline script and a menu that depends on a bundle finishing is a
   menu that is missing exactly when the connection is bad. site.js only closes
   it after a click on a same-page anchor, and the menu works without that. */

.nav__more { display: none; }
@media (max-width: 900px) { .nav__more { display: block; margin-left: auto; } }

.nav__more > summary {
  list-style: none;
  cursor: pointer;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink-muted);
  transition: color 200ms var(--ease), border-color 200ms var(--ease);
}
.nav__more > summary::-webkit-details-marker { display: none; }
.nav__more > summary:hover,
.nav__more[open] > summary { color: var(--ink); border-color: color-mix(in srgb, var(--teal) 40%, var(--line)); }
.nav__more > summary svg { width: 18px; height: 18px; }
.nav__more[open] .i-bars { display: none; }
.nav__more:not([open]) .i-close { display: none; }

/* Anchored to `.nav` (which is `position: fixed`), NOT to the button. The
   button is not on the right edge — the theme toggle and the CTA follow it —
   so a panel with `right: 0` on its own positioned parent opened off the left
   side of a 390px screen, invisible. Hanging it off the header instead is the
   only anchor that stays put wherever the button ends up in the row. */
.nav__panel {
  position: absolute;
  top: calc(100% + 10px);
  /* The gutter, so the panel lines up with the shell the header sits in
     rather than with the window edge. Only ever shown below 900px, where the
     shell is the viewport minus two gutters. */
  right: var(--gutter);
  z-index: 60;
  min-width: 232px;
  max-width: calc(100vw - 32px);
  display: grid;
  gap: 2px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--card-shadow), 0 18px 40px rgba(0, 0, 0, 0.28);
}
.nav__panel a {
  font-family: var(--display);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 11px 12px;
  border-radius: var(--r-pill);
}
.nav__panel a:hover { color: var(--ink); background: var(--surface-alt); }
.nav__panel a[aria-current="page"] { color: var(--ink); background: var(--surface-alt); }
.nav__panel hr { border: 0; border-top: 1px solid var(--line); margin: 6px 4px; }

/* Below 620px the row is crest + menu + languages + theme + CTA, and that is
   one item too many: the CTA's label was being clipped by its own pill. The
   language switcher is the one that loses, because it is the only control with
   a full-width home inside the panel — the theme toggle and the CTA have
   nowhere else to be. */
@media (max-width: 620px) {
  .nav .lang { display: none; }
}
.nav__panel .nav__panel-langs { display: none; }
@media (max-width: 620px) {
  .nav__panel .nav__panel-langs { display: contents; }
}

/* On a phone the wordmark, the theme toggle and a full-size CTA do not fit on
   one line. Shrink the CTA rather than wrapping it — the hero's own primary
   action is a thumb-flick away regardless. */
.nav__cta { padding: 12px 20px; }

@media (max-width: 620px) {
  .nav__cta { padding: 10px 15px; font-size: 11.5px; letter-spacing: 0.06em; }
  .nav__cta .btn__arrow { display: none; }
  .wordmark { font-size: 11px; letter-spacing: 0.14em; }
}

/* ---------- controls ------------------------------------------------------ */

.btn {
  --btn-bg: var(--surface-alt);
  --btn-fg: var(--ink);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 26px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--display);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: transform 320ms var(--ease), border-color 260ms var(--ease),
    background-color 260ms var(--ease), box-shadow 320ms var(--ease);
  will-change: transform;
}
.btn:hover { border-color: var(--ink-faint); }
.btn:active { transform: scale(0.975); }

/* the one primary action, and the app's one glow (BlPalette.accentGlow) */
.btn--primary {
  border-color: transparent;
  color: var(--on-accent);
  background: linear-gradient(100deg, var(--accent-hot), var(--accent-deep));
  box-shadow: 0 8px 24px -4px color-mix(in srgb, var(--accent) 25%, transparent);
}
.btn--primary::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, 0.42), transparent 80%);
  transform: translateX(-120%);
}
.btn--primary:hover {
  box-shadow: 0 14px 38px -6px color-mix(in srgb, var(--accent) 42%, transparent);
}
.btn--primary:hover::after { animation: sheen 900ms var(--ease); }
@keyframes sheen { to { transform: translateX(120%); } }

.btn__arrow { transition: transform 320ms var(--ease); }
.btn:hover .btn__arrow { transform: translateX(4px); }

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-soft);
  cursor: pointer;
  transition: transform 300ms var(--ease), color 220ms, border-color 220ms;
}
.icon-btn:hover { color: var(--ink); border-color: var(--ink-faint); transform: rotate(-18deg); }
.icon-btn svg { width: 18px; height: 18px; }
:root[data-theme='light'] .icon-btn .i-moon { display: none; }
:root:not([data-theme='light']) .icon-btn .i-sun { display: none; }

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

.hero {
  min-height: 100svh;
  display: grid;
  align-items: center;
  padding-block: 118px 56px;
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(30px, 5vw, 70px);
  align-items: center;
}
@media (max-width: 980px) {
  .hero__grid { grid-template-columns: 1fr; }
  .hero { min-height: auto; padding-block: 120px 40px; }
}

.hero__copy { display: flex; flex-direction: column; gap: 26px; }

/* The crest above the masthead. The nav mark is small enough to read as
   chrome; this is the one place the identity is allowed to be the size it
   actually is, so it sits on its own line over the overline and shares that
   row's bottom margin rather than adding a gap of its own. */
.hero__crest {
  display: block;
  width: clamp(74px, 9vw, 108px);
  height: auto;
  margin-bottom: -8px;
  filter: drop-shadow(0 10px 26px rgba(0, 0, 0, 0.42));
}
[data-theme="light"] .hero__crest {
  filter: drop-shadow(0 0 0.6px rgba(22, 25, 27, 0.5)) drop-shadow(0 10px 24px rgba(0, 0, 0, 0.18));
}

/* word-by-word mask reveal */
.reveal-line { display: block; overflow: hidden; padding-bottom: 0.06em; }
.reveal-line > span {
  display: block;
  transform: translateY(105%);
  animation: riseIn 1150ms var(--ease) forwards;
}
.reveal-line:nth-of-type(1) > span { animation-delay: 120ms; }
.reveal-line:nth-of-type(2) > span { animation-delay: 220ms; }
.reveal-line:nth-of-type(3) > span { animation-delay: 320ms; }
@keyframes riseIn { to { transform: translateY(0); } }

.fade-up {
  opacity: 0;
  transform: translateY(16px);
  animation: fadeUp 900ms var(--ease) forwards;
}
@keyframes fadeUp { to { opacity: 1; transform: none; } }
.d1 { animation-delay: 460ms; }
.d2 { animation-delay: 580ms; }
.d3 { animation-delay: 700ms; }
.d4 { animation-delay: 820ms; }

.hero__cta { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }

.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  align-items: center;
  color: var(--ink-muted);
  font-size: 13px;
}
.dot { width: 5px; height: 5px; border-radius: 50%; background: var(--good); box-shadow: 0 0 0 0 color-mix(in srgb, var(--good) 60%, transparent); animation: pulse 2.4s infinite; }
@keyframes pulse {
  70% { box-shadow: 0 0 0 9px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* Qui stavano ~350 righe per il mock animato del telefono, ereditate dal
   portale del progetto di origine e mai collegate a niente: nessun HTML e
   nessun JS di questo sito nomina una classe `.ph-*`. La sostituzione era
   gia' documentata in testa a `assets/js/site.js` -- «no animated phone
   mock (the screenshots are real captures, and a capture does not need a
   puppet show)» -- ma il CSS era rimasto, e descriveva l'interfaccia di
   un altro gioco: la fascia con la squadra, le stelle del club, il
   chip della posizione in campo. Tolte il 09/08/2026. */

/* ---------- marquee ------------------------------------------------------ */

.marquee {
  border-block: 1px solid var(--line);
  background: color-mix(in srgb, var(--band) 60%, transparent);
  overflow: hidden;
  padding-block: 16px;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee__track {
  display: flex;
  gap: 46px;
  width: max-content;
  animation: slide 46s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes slide { to { transform: translateX(-50%); } }
.marquee__item {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}
.marquee__item b { color: var(--ink); font-size: 15px; font-variant-numeric: tabular-nums; }
.marquee__item::after { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--teal); margin-left: 36px; align-self: center; }

/* ---------- reveal on scroll --------------------------------------------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 900ms var(--ease), transform 900ms var(--ease);
  transition-delay: var(--rd, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* ---------- pillars ------------------------------------------------------ */

.pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
  gap: 16px;
}
.card {
  position: relative;
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: 26px 24px 28px;
  box-shadow: var(--card-shadow);
  overflow: hidden;
  transition: transform 480ms var(--ease), border-color 380ms var(--ease), box-shadow 480ms var(--ease);
}
.card::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 480ms var(--ease);
  background: radial-gradient(340px 240px at var(--mx, 50%) var(--my, 0%), color-mix(in srgb, var(--teal) 12%, transparent), transparent 70%);
}
.card:hover {
  transform: translateY(-5px);
  border-color: color-mix(in srgb, var(--teal) 40%, var(--line));
  box-shadow: 0 18px 44px -20px rgba(0, 0, 0, 0.5);
}
:root[data-theme='light'] .card:hover { box-shadow: 0 18px 44px -22px rgba(22, 25, 27, 0.28); }
.card:hover::before { opacity: 1; }
.card > * { position: relative; }

.card__idx {
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--teal-text);
  display: block;
  margin-bottom: 16px;
}
.card p { color: var(--ink-soft); font-size: 14.5px; margin: 12px 0 0; }

/* ---------- arc / timeline ----------------------------------------------- */

.arc { position: relative; padding-left: 34px; }
.arc__spine {
  position: absolute;
  left: 7px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: var(--line-strong);
  border-radius: 2px;
  overflow: hidden;
}
.arc__spine i {
  position: absolute;
  inset: 0 0 auto 0;
  height: 0;
  background: linear-gradient(180deg, var(--teal), var(--accent));
  border-radius: 2px;
}
.arc__step {
  position: relative;
  padding: 20px 0 26px;
  border-bottom: 1px solid var(--line);
}
.arc__step:last-child { border-bottom: 0; }
.arc__step::before {
  content: '';
  position: absolute;
  left: -34px;
  top: 27px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--line-strong);
  background: var(--base);
  transition: border-color 420ms var(--ease), background-color 420ms var(--ease), transform 420ms var(--ease);
}
.arc__step.is-in::before {
  border-color: var(--accent);
  background: var(--accent);
  transform: scale(1.12);
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 14%, transparent);
}
.arc__age {
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.arc__step h3 { font-size: clamp(1.5rem, 3.4vw, 2.2rem); margin: 6px 0 8px; }
.arc__step p { color: var(--ink-soft); margin: 0; max-width: 60ch; font-size: 15px; }

/* ---------- bento -------------------------------------------------------- */

.bento {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 16px;
}
.bento > .card { grid-column: span 2; }
.bento > .card.w3 { grid-column: span 3; }
.bento > .card.w4 { grid-column: span 4; }
.bento > .card.w6 { grid-column: span 6; }
.bento > .card.w6 p { max-width: 88ch; }
@media (max-width: 900px) {
  .bento { grid-template-columns: repeat(2, 1fr); }
  .bento > .card, .bento > .card.w3, .bento > .card.w4, .bento > .card.w6 { grid-column: span 2; }
}

.attr-demo { display: grid; gap: 9px; margin-top: 18px; }
.attr-demo__row { display: flex; align-items: center; gap: 10px; }
.attr-demo__row span {
  font-family: var(--display); font-size: 10px; font-weight: 700;
  letter-spacing: 0.11em; color: var(--ink-muted); width: 96px;
}
.attr-demo__row b { font-family: var(--display); font-size: 13px; width: 26px; text-align: right; font-variant-numeric: tabular-nums; }
.attr-demo .bar { height: 5px; }

.tag-row { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 18px; }
.tag {
  font-family: var(--display);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  padding: 6px 11px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  color: var(--ink-muted);
  transition: color 240ms, border-color 240ms, transform 240ms var(--ease);
}
.tag:hover { color: var(--teal-text); border-color: var(--teal); transform: translateY(-2px); }

/* ---------- odds --------------------------------------------------------- */

.odds {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 16px;
  margin-top: 8px;
}
.odd {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  padding: 26px 24px;
  box-shadow: var(--card-shadow);
}
.odd b {
  display: block;
  font-family: var(--display);
  font-size: clamp(2.6rem, 6vw, 3.9rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.odd .odd__k { color: var(--teal); }
.odd .odd__a { color: var(--accent); }
.odd p { margin: 12px 0 0; color: var(--ink-soft); font-size: 14px; }
.odd small { display: block; margin-top: 10px; color: var(--ink-faint); font-size: 11.5px; }

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

.gallery {
  display: flex;
  gap: clamp(18px, 4vw, 46px);
  justify-content: center;
  flex-wrap: wrap;
  align-items: flex-start;
}
.gallery figure { margin: 0; display: grid; gap: 18px; justify-items: center; }
.gallery figcaption { text-align: center; max-width: 30ch; }
.gallery figcaption b { display: block; font-family: var(--display); font-size: 15px; letter-spacing: -0.01em; }
.gallery figcaption span { color: var(--ink-muted); font-size: 13.5px; }

/* ---------- signup ------------------------------------------------------- */

.signup {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--sheet-shadow);
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
}
@media (max-width: 900px) { .signup { grid-template-columns: 1fr; } }

.signup::before {
  content: '';
  position: absolute;
  inset: -2px;
  z-index: 0;
  pointer-events: none;
  background: conic-gradient(from var(--ang, 0deg), transparent 0 62%, color-mix(in srgb, var(--accent) 55%, transparent) 76%, color-mix(in srgb, var(--teal) 55%, transparent) 88%, transparent 100%);
  opacity: 0.5;
  mask: linear-gradient(#000, #000) content-box, linear-gradient(#000, #000);
  mask-composite: exclude;
  -webkit-mask: linear-gradient(#000, #000) content-box, linear-gradient(#000, #000);
  -webkit-mask-composite: xor;
  padding: 1.5px;
  border-radius: inherit;
  animation: spinBorder 9s linear infinite;
}
@property --ang { syntax: '<angle>'; initial-value: 0deg; inherits: false; }
@keyframes spinBorder { to { --ang: 360deg; } }

.signup__aside {
  position: relative;
  z-index: 1;
  padding: clamp(30px, 4vw, 46px);
  background: linear-gradient(160deg, var(--teal-wash), transparent 65%);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 22px;
}
@media (max-width: 900px) { .signup__aside { border-right: 0; border-bottom: 1px solid var(--line); } }
.signup__aside h2 { font-size: clamp(1.9rem, 4vw, 2.7rem); }
.perks { list-style: none; margin: 0; padding: 0; display: grid; gap: 13px; }
.perks li { display: flex; gap: 11px; font-size: 14.5px; color: var(--ink-soft); }
.perks li::before {
  content: '';
  flex: none;
  width: 7px; height: 7px;
  margin-top: 8px;
  border-radius: 50%;
  background: var(--teal);
}
.counter-line {
  margin-top: auto;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-muted);
}
.counter-line b { color: var(--ink); font-family: var(--display); font-variant-numeric: tabular-nums; }

.signup__form { position: relative; z-index: 1; padding: clamp(30px, 4vw, 46px); }

.field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 560px) { .field-grid { grid-template-columns: 1fr; } }

.field { display: grid; gap: 7px; margin-bottom: 14px; position: relative; }
.field > label {
  font-family: var(--display);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.field input {
  width: 100%;
  padding: 14px 15px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--surface-alt);
  color: var(--ink);
  font-size: 15px;
  transition: border-color 240ms var(--ease), box-shadow 240ms var(--ease), background-color 240ms;
}
.field input::placeholder { color: var(--ink-faint); }
.field input:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 18%, transparent);
}
.field input[aria-invalid='true'] {
  border-color: var(--bad);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bad) 16%, transparent);
}
.field__in { position: relative; }
.field__in .prefix {
  position: absolute;
  left: 15px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--ink-faint);
  font-size: 15px;
  pointer-events: none;
}
.field__in.has-prefix input { padding-left: 31px; }
.err {
  font-size: 12px;
  color: var(--bad);
  min-height: 15px;
  opacity: 0;
  transform: translateY(-3px);
  transition: opacity 200ms, transform 200ms;
}
.err.show { opacity: 1; transform: none; }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.submit-row { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 8px; }
.btn--submit { min-width: 210px; }
.btn.is-busy { pointer-events: none; opacity: 0.8; }
.spinner {
  width: 15px; height: 15px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--on-accent) 35%, transparent);
  border-top-color: var(--on-accent);
  animation: spin 700ms linear infinite;
  display: none;
}
.btn.is-busy .spinner { display: block; }
.btn.is-busy .btn__label, .btn.is-busy .btn__arrow { display: none; }
@keyframes spin { to { transform: rotate(360deg); } }

.fineprint { font-size: 12px; color: var(--ink-faint); max-width: 44ch; line-height: 1.5; }
.fineprint a { color: var(--ink-muted); text-decoration: underline; text-underline-offset: 2px; }

.form-note {
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: var(--r-md);
  font-size: 13.5px;
  display: none;
}
.form-note.show { display: block; animation: fadeUp 400ms var(--ease) both; }
.form-note--bad { background: color-mix(in srgb, var(--bad) 12%, transparent); color: var(--bad); border: 1px solid color-mix(in srgb, var(--bad) 34%, transparent); }

/* success takeover */
.success {
  display: none;
  text-align: left;
}
.success.show { display: block; }
.signup.is-done .signup__form form { display: none; }
.success__mark {
  width: 62px; height: 62px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: linear-gradient(140deg, var(--accent-hot), var(--accent-deep));
  box-shadow: 0 12px 34px -8px color-mix(in srgb, var(--accent) 50%, transparent);
  margin-bottom: 24px;
}
.success__mark svg { width: 28px; height: 28px; stroke: var(--on-accent); }
.success__mark svg path { stroke-dasharray: 30; stroke-dashoffset: 30; animation: draw 620ms var(--ease) 160ms forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
.success h3 { font-size: clamp(1.7rem, 3.6vw, 2.4rem); margin-bottom: 12px; }
.success p { color: var(--ink-soft); margin: 0 0 22px; }
.success__no {
  display: inline-flex;
  align-items: baseline;
  gap: 12px;
  padding: 16px 22px;
  border-radius: var(--r-md);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  margin-bottom: 22px;
}
.success__no span { font-family: var(--display); font-size: 10px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-muted); }
.success__no b { font-family: var(--display); font-size: 2.4rem; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; letter-spacing: -0.03em; }

/* ---------- socials ------------------------------------------------------ */

.socials { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 700px) { .socials { grid-template-columns: 1fr; } }

.social {
  position: relative;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 30px 28px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  overflow: hidden;
  transition: transform 460ms var(--ease), border-color 320ms var(--ease);
}
.social::after {
  content: '';
  position: absolute;
  inset: auto -30% -80% -30%;
  height: 160%;
  background: radial-gradient(50% 50% at 50% 50%, var(--glow, var(--teal)), transparent 70%);
  opacity: 0;
  transform: translateY(20%);
  transition: opacity 520ms var(--ease), transform 620ms var(--ease);
}
.social:hover { transform: translateY(-4px); border-color: var(--ink-faint); }
.social:hover::after { opacity: 0.16; transform: translateY(0); }
.social > * { position: relative; }
.social__ico {
  width: 50px; height: 50px;
  flex: none;
  display: grid; place-items: center;
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--surface-alt);
  transition: transform 460ms var(--ease);
}
.social:hover .social__ico { transform: rotate(-8deg) scale(1.06); }
.social__ico svg { width: 24px; height: 24px; }
.social b { display: block; font-family: var(--display); font-size: 17px; letter-spacing: -0.01em; }
.social span { color: var(--ink-muted); font-size: 13.5px; }
.social__go { margin-left: auto; color: var(--ink-faint); transition: transform 380ms var(--ease), color 260ms; }
.social:hover .social__go { transform: translate(4px, -4px); color: var(--ink); }

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

.footer { border-top: 1px solid var(--line); padding-block: 48px 40px; margin-top: 40px; }
.footer__grid {
  display: flex;
  flex-wrap: wrap;
  gap: 26px;
  align-items: flex-start;
  justify-content: space-between;
}
.footer p { color: var(--ink-faint); font-size: 12.5px; max-width: 62ch; margin: 14px 0 0; line-height: 1.6; }
.footer__links { display: flex; gap: 18px; flex-wrap: wrap; }
.footer__links a { color: var(--ink-muted); font-size: 13px; transition: color 200ms; }
.footer__links a:hover { color: var(--ink); }

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal-line > span { transform: none; }
  [data-reveal] { opacity: 1; transform: none; }
  .fade-up { opacity: 1; transform: none; }
  .spot { display: none; }
}

/* ==========================================================================
   Content pages — /games-like-bitlife/, /faq/ and their Spanish twins.
   These exist to be *found*: long-form answers to the questions people
   actually type. They reuse every token above, so they cannot drift from the
   home page's look, and they add only what prose needs.
   ========================================================================== */

/* ---------- language switcher -------------------------------------------- */

.lang {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  overflow: hidden;
  flex: none;
}
.lang a {
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 9px 12px;
  color: var(--ink-muted);
  transition: color 200ms var(--ease), background-color 200ms var(--ease);
}
.lang a:hover { color: var(--ink); background: var(--surface-alt); }
.lang a[aria-current='true'] { color: var(--on-teal); background: var(--teal); }
@media (max-width: 620px) { .lang a { padding: 8px 10px; font-size: 10px; } }

/* ---------- the h1 lockup's category line -------------------------------- */

/* Visible, not a hidden keyword stuff: the page's <h1> has to say what the
   thing *is*, and "Wonderkid" alone says nothing to a stranger or a
   crawler. Sized down so the lockup still reads as a wordmark. */
.h-display__sub {
  display: block;
  margin-top: 0.34em;
  font-size: clamp(1.05rem, 1.9vw, 1.45rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--ink-soft);
}

/* ---------- page hero (content pages) ------------------------------------ */

.page-hero { padding: 150px 0 clamp(40px, 6vw, 64px); }
.page-hero h1 {
  font-size: clamp(2.3rem, 5.4vw, 4rem);
  letter-spacing: -0.035em;
  margin-bottom: 20px;
  max-width: 20ch;
}
.page-hero .lede { max-width: 62ch; }

.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 20px;
  font-family: var(--display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.crumbs a { color: var(--teal-text); }
.crumbs a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* The first crumb is always the way home, and off the home page it is the only
   one besides the wordmark — the header deliberately carries pages, not a Home
   link (see the note in the nav markup). At 11px, unpadded and unmarked it read
   as a label rather than a way back. The arrow and the padded hit area say
   "clickable" and give it a thumb-sized target, without a second Home in the
   header. Negative margins pay the padding back so the row keeps its box and
   nothing below shifts. */
.crumbs a:first-child {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: -6px -4px -6px -10px;
  padding: 6px 10px;
  border-radius: 999px;
  transition: color 200ms var(--ease), background-color 200ms var(--ease);
}
.crumbs a:first-child::before {
  content: '←';
  font-size: 14px;
  line-height: 1;
  transition: transform 200ms var(--ease);
}
.crumbs a:first-child:hover {
  color: var(--ink);
  background: var(--surface-alt);
  text-decoration: none;
}
.crumbs a:first-child:hover::before { transform: translateX(-3px); }

/* ---------- prose -------------------------------------------------------- */

.prose { max-width: 72ch; }
.prose > * + * { margin-top: 1.15em; }
.prose p, .prose li { font-size: 17px; line-height: 1.68; color: var(--ink-soft); }
.prose h2 {
  font-size: clamp(1.6rem, 3.4vw, 2.25rem);
  letter-spacing: -0.03em;
  margin-top: 2.2em;
  margin-bottom: 0.1em;
  color: var(--ink);
  scroll-margin-top: 90px;
}
.prose h3 {
  font-size: 1.2rem;
  margin-top: 1.9em;
  margin-bottom: 0.1em;
  color: var(--ink);
}
.prose strong { color: var(--ink); font-weight: 700; }
.prose em { color: var(--ink); font-style: italic; }
.prose a {
  color: var(--teal-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color 180ms var(--ease);
}
.prose a:hover { color: var(--accent); }
.prose ul, .prose ol { padding-left: 1.25em; margin-block: 1.1em; }
.prose li + li { margin-top: 0.55em; }
.prose li::marker { color: var(--teal); }
.prose blockquote {
  margin: 1.8em 0;
  padding: 4px 0 4px 22px;
  border-left: 2px solid var(--accent);
}
.prose blockquote p { color: var(--ink); font-size: 18px; }

/* A pull-stat inside prose — the one place a number gets to shout. */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px;
  margin: 2em 0;
  max-width: none;
}
.stat-strip div {
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: var(--r-md);
  padding: 18px 18px 20px;
  box-shadow: var(--card-shadow);
}
.stat-strip b {
  display: block;
  font-family: var(--display);
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--teal);
  line-height: 1;
}
.stat-strip span { display: block; margin-top: 8px; font-size: 13.5px; color: var(--ink-muted); }

/* ---------- comparison table --------------------------------------------- */

/* Wide content scrolls inside its own box — the page body never does. */
.cmp-wrap {
  overflow-x: auto;
  margin: 2em 0;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--card-shadow);
  -webkit-overflow-scrolling: touch;
}
.cmp { width: 100%; border-collapse: collapse; min-width: 560px; }
.cmp th, .cmp td {
  text-align: left;
  padding: 15px 18px;
  border-bottom: 1px solid var(--line);
  font-size: 14.5px;
  vertical-align: top;
}
.cmp thead th {
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-muted);
  background: var(--surface-alt);
  white-space: nowrap;
}
.cmp tbody th {
  font-family: var(--display);
  font-weight: 700;
  font-size: 14.5px;
  color: var(--ink);
  width: 30%;
}
.cmp td { color: var(--ink-soft); }
.cmp tr:last-child th, .cmp tr:last-child td { border-bottom: 0; }
.cmp .yes { color: var(--good); font-weight: 700; }
.cmp .no { color: var(--bad); font-weight: 700; }
.cmp col.us { background: color-mix(in srgb, var(--teal) 6%, transparent); }

/* ---------- FAQ accordion ------------------------------------------------ */

/* <details> rather than JS: the answer is in the DOM whether or not it is
   open, so a crawler reads all of it, and it works with scripting off. */
.faq { max-width: 78ch; display: grid; gap: 12px; }
.faq details {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--card-shadow);
  overflow: hidden;
  transition: border-color 260ms var(--ease);
}
.faq details[open] { border-color: color-mix(in srgb, var(--teal) 40%, var(--line)); }
.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 20px 56px 20px 22px;
  position: relative;
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '';
  position: absolute;
  right: 24px;
  top: 50%;
  width: 11px;
  height: 11px;
  margin-top: -7px;
  border-right: 2px solid var(--teal);
  border-bottom: 2px solid var(--teal);
  transform: rotate(45deg);
  transition: transform 320ms var(--ease);
}
.faq details[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.faq summary:hover { color: var(--teal-text); }
.faq .answer { padding: 0 22px 22px; }
.faq .answer > * + * { margin-top: 0.9em; }
.faq .answer p, .faq .answer li { font-size: 15.5px; line-height: 1.65; color: var(--ink-soft); margin: 0; }
.faq .answer ul { padding-left: 1.2em; }
.faq .answer a { color: var(--teal-text); text-decoration: underline; text-underline-offset: 3px; }

/* ---------- closing CTA on content pages --------------------------------- */

.cta-band {
  margin-top: clamp(60px, 9vw, 100px);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: linear-gradient(160deg, var(--teal-wash), transparent 70%), var(--surface);
  padding: clamp(30px, 5vw, 52px);
  box-shadow: var(--card-shadow);
}
.cta-band h2 { font-size: clamp(1.7rem, 3.6vw, 2.5rem); margin-bottom: 14px; }
.cta-band p { color: var(--ink-soft); max-width: 56ch; margin: 0 0 26px; }

/* ---------- «Play», e la spunta del test Android -------------------------
   Il teal e non l'arancione, per la regola in testa a questo file: l'arancione
   è il 10% del budget e va a ciò che MUOVE qualcosa — qui è il pulsante di
   iscrizione. Una seconda voce arancione accanto non aggiunge enfasi, la
   divide. */

.nav__link--play { color: var(--teal-text); font-weight: 700; }
.nav__link--play:hover { color: var(--teal); }

.opt-in {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface-alt);
  padding: 14px 16px;
  margin-bottom: 18px;
  transition: border-color 260ms var(--ease), background 260ms var(--ease);
}
/* Acceso: il riquadro si tinge appena, così la spunta si vede senza guardare
   la casella — che su un telefono è larga diciassette pixel. */
.opt-in.is-on {
  border-color: var(--teal-deep);
  background: linear-gradient(160deg, var(--teal-wash), transparent 70%), var(--surface-alt);
}
.opt-in__row { display: flex; gap: 11px; align-items: flex-start; cursor: pointer; }
.opt-in__row input { margin: 3px 0 0; width: 17px; height: 17px; accent-color: var(--teal); flex: none; }
.opt-in__row b { display: block; font-family: var(--display); font-size: .95rem; }
.opt-in__note { display: block; margin: 4px 0 0; font-size: .82rem; color: var(--ink-muted); line-height: 1.5; }
.opt-in__extra { margin: 14px 0 0; padding-top: 14px; border-top: 1px solid var(--line); }
.opt-in__extra label { font-size: .82rem; }

.success__beta {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: .92rem;
  color: var(--ink-muted);
}

/* ---------- related links ------------------------------------------------ */

.related { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; margin-top: 20px; }
.related a {
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  padding: 22px 24px;
  box-shadow: var(--card-shadow);
  transition: transform 420ms var(--ease), border-color 300ms var(--ease);
}
.related a:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--teal) 40%, var(--line)); }
.related b { display: block; font-family: var(--display); font-size: 1.05rem; letter-spacing: -0.01em; }
.related span { display: block; margin-top: 7px; font-size: 14px; color: var(--ink-muted); }

/* ---------- devlog ------------------------------------------------------- */
/* One column, not the auto-fit grid `.related` uses: these are dated entries
   read in order, and a two-column grid reads as "pick one" rather than "newest
   first". */

/* Width and centring are NOT set here — they come from the shared `--measure`
   rule further down, the one `.prose` and the page-hero headings use. Setting
   a second opinion here is what put this list out of register in the first
   place. */
.log { display: grid; gap: 14px; }
.log a {
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  padding: 22px 24px;
  box-shadow: var(--card-shadow);
  transition: transform 420ms var(--ease), border-color 300ms var(--ease);
}
.log a:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--teal) 40%, var(--line)); }
.log time,
.post__meta {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.log b { display: block; margin-top: 6px; font-family: var(--display); font-size: 1.12rem; letter-spacing: -0.01em; }
.log span { display: block; margin-top: 8px; font-size: 15px; line-height: 1.6; color: var(--ink-muted); }
.post__meta { margin-bottom: 12px; }

/* ---------- footer nav columns ------------------------------------------- */

.footer__nav { display: flex; flex-wrap: wrap; gap: 40px; }
.footer__col { display: grid; gap: 10px; align-content: start; }
.footer__col b {
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.footer__col a { color: var(--ink-soft); font-size: 14px; transition: color 200ms; }
.footer__col a:hover { color: var(--ink); }

/* ---------- 404 ----------------------------------------------------------- */

.notfound { min-height: 72svh; display: grid; align-content: center; gap: 22px; }
.notfound .code {
  font-family: var(--display);
  font-size: clamp(4rem, 14vw, 9rem);
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 0.9;
  color: var(--teal);
}

/* ---------- editorial layout for the content pages ------------------------
   A 72ch measure pinned to the left of a 1220px shell reads as a page that
   forgot to finish. Centre the column and let the two elements that *want*
   width — the comparison table and the stat strip — break out of it. */

/* `ch` is relative to the element's OWN font-size, so 72ch on a 64px <h1> is
   about 2600px and the cap does nothing — which is exactly how the heading
   ended up flush left while the body was centred. One fixed measure instead. */
.page-hero .crumbs,
.page-hero h1,
.page-hero .lede { max-width: var(--measure); margin-inline: auto; }

/* The devlog index belongs to the same column. Left out of this rule it fell
   back to its own `72ch`, which resolves against the element's font-size and
   came out 57px narrower — enough to sit visibly out of register with the
   headline directly above it. Same trap the <h1> fell into, one line up. */
.prose,
.log { max-width: var(--measure); margin-inline: auto; }
.prose > .cmp-wrap,
.prose > .stat-strip {
  width: min(100%, 940px);
  margin-inline: calc(50% - min(50%, 470px));
}
@media (max-width: 900px) {
  .prose > .cmp-wrap,
  .prose > .stat-strip { width: 100%; margin-inline: 0; }
}

.cta-band, .related { max-width: 940px; margin-inline: auto; }

/* the FAQ list is its own column and wants the same treatment */
.faq { margin-inline: auto; }

/* ==========================================================================
   Magnate — real captures in a plain frame
   --------------------------------------------------------------------------
   The origin project's hero is an HTML mock that plays itself; Magnate's game
   is live, so the hero and the gallery show actual captures instead. The
   frame is deliberately simple — border, radius, shadow — because the capture
   already contains a full UI: putting chrome around chrome is noise. The
   captures come in a dark and a light take of the same life, and the toggle
   swaps them with a `[data-theme]` rule rather than a media query.
   ========================================================================== */

.shot {
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--sheet-shadow);
}
.shot img { display: block; width: 100%; height: auto; }
/* Two class selectors, not one: `.shot img` above is class+type (0-1-1) and
   would out-rank a bare `.shot__light` (0-1-0), leaving both takes visible. */
.shot .shot__light { display: none; }
:root[data-theme='light'] .shot .shot__dark { display: none; }
:root[data-theme='light'] .shot .shot__light { display: block; }

/* The hero is the exception to the two rules above and carries no skin class
   at all: it is a recording of a real turn, it exists in four takes (dark and
   light, moving and frozen), and at 160-220 KB each they cannot all be
   downloaded so three can be hidden. That choice lives in `<source media>` in
   the markup and in `heroSkin` in site.js — see the comment on the hero. The
   gallery below keeps the CSS swap: its stills are 20 KB and four of them
   cost less than one decision. */

/* the hero capture: same slot the phone mock occupied, same lean */
.shot-stage {
  display: grid;
  justify-items: center;
  align-content: center;
  perspective: 1600px;
}
.shot-stage .shot {
  width: min(340px, 80vw);
  transform: rotateY(-10deg) rotateX(4deg) rotateZ(-1deg);
  transition: transform 600ms var(--ease);
}
@media (max-width: 980px) {
  .shot-stage .shot { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .shot-stage .shot { transform: none; }
}

/* the gallery reuses its figure grid, swapping phones for frames */
.gallery .shot { width: min(300px, 82vw); transition: transform 700ms var(--ease); }
.gallery .g1 .shot { transform: rotate(-2.2deg); }
.gallery .g3 .shot { transform: rotate(2.2deg); }
.gallery figure:hover .shot { transform: translateY(-10px) rotate(0deg); }

/* the two-tone wordmark inside the display title, same split as the app bar */
.h-display i { color: var(--teal-text); font-style: normal; }
