/* Public site — the landing page (/index.html) and the public legal pages
 * (/privacy.html, /terms.html, which add legal.css on top of this).
 *
 * Loads after tokens.css. No external fonts, no CDN, no build step.
 *
 * Brand ground: void_black (#0B0D13) = brand.json rules.approved_backgrounds[0],
 * therefore the COLOUR mark is the correct variant here
 * (brand.json rules.background_variant.dark = "mark_colour").
 *
 * MOBILE-FIRST. The rules outside any @media block ARE the phone layout; every
 * media query below only adds to them, none of them takes anything away.
 * Breakpoints (all min-width, all in rem so they respect the user's font size):
 *
 *   base          0 – 359px   one column, 1rem gutter, smallest type step
 *   >= 22.5rem      360px+    1.25rem gutter, comfortable phone layout
 *   >= 48rem        768px+    3-up card grid, 2rem gutter, tablet type
 *   >= 64rem       1024px+    page hits its max measure, largest type step
 *
 * Nothing in here may produce a horizontal scrollbar at 360px. Everything
 * tappable is at least --tap-min (44px) tall.
 */

/* ---------------------------------------------------------------------------
 * DERIVED LAYER — these are NOT brand tokens.
 *
 * tokens.css is copied verbatim from brand.json and is authoritative; nothing
 * here edits it and nothing here invents a hue. Every colour below is one of
 * the six brand colours at a lower alpha (a tint of a token, not a new colour).
 * The non-colour values are geometry brand.json simply does not define: radii
 * larger than --radius-lg, glow sizes, the tap-target floor, the page gutter.
 * They live in this file precisely so tokens.css stays a pure mirror.
 * ------------------------------------------------------------------------ */
:root {
  /* shape — rounder than the token set goes, for the friendlier card look */
  --radius-xl: 28px;
  --radius-2xl: 34px;

  /* layout */
  --gutter: 1rem;
  --page-max: 64rem;
  --tap-min: 44px;

  /* surfaces: void_black_raised over void_black, both approved grounds */
  --surface-1: rgba(19, 20, 25, 0.72);
  --surface-2: rgba(19, 20, 25, 0.92);
  --hairline: rgba(194, 193, 193, 0.14);
  --hairline-strong: rgba(194, 193, 193, 0.26);

  /* soft light — low-alpha bright_violet / deep_violet / signal_cyan.
   * Deliberately wide and faint: the brief is "soft glow", not neon edge. */
  --glow-violet: rgba(116, 47, 201, 0.22);
  --glow-violet-faint: rgba(116, 47, 201, 0.1);
  --glow-indigo: rgba(51, 20, 85, 0.5);
  --glow-cyan: rgba(52, 212, 220, 0.09);

  /* text */
  --text-soft: rgba(194, 193, 193, 0.78);
  --text-faint: rgba(194, 193, 193, 0.55);

  /* a lifted bright_violet for hover — same hue, lightened, no new colour */
  --violet-lift: #8a45e0;
}

body {
  background-color: var(--void-black);
  color: var(--silver);
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  /* Belt and braces against a stray wide child on a 360px phone. */
  overflow-x: hidden;
}

/* The void: a flat brand ground with three soft, wide light sources. Pure CSS
 * so the page stays HTML + two CSS files + one small PNG on the wire.
 * Fixed + inset:0 rather than a body background so it never scrolls or seams. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(
      80% 55% at 50% 12%,
      var(--glow-violet) 0%,
      rgba(116, 47, 201, 0) 72%
    ),
    radial-gradient(
      95% 60% at 50% 100%,
      var(--glow-indigo) 0%,
      rgba(51, 20, 85, 0) 78%
    ),
    radial-gradient(
      55% 40% at 88% 66%,
      var(--glow-cyan) 0%,
      rgba(52, 212, 220, 0) 72%
    );
}

.skip-link {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -120%);
  background: var(--bright-violet);
  color: var(--ice-white);
  padding: 0.6rem 1rem;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  text-decoration: none;
  z-index: 10;
}

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

/* Shared page shell -------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

.hero {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: clamp(2.25rem, 10vw, 6rem) var(--gutter) clamp(2rem, 7vw, 3.5rem);
}

.lockup {
  width: 100%;
  max-width: 28.75rem; /* 460px */
  margin: 0 auto;
}

/* Clear space: brand.json rules.clear_space_ratio = 0.25 of the MARK's width on
 * every side. The art fills its own canvas edge to edge (verified: the derived
 * PNG's alpha bounding box is the full canvas), so this padding IS the clear
 * space.
 *
 * It is calc(var(--art) * 0.25) and not "padding: 25%", because a percentage
 * padding resolves against the PARENT's width, not the element's own — which
 * silently collapses the mark to zero width on a wide viewport. content-box
 * keeps --art the size of the artwork with the clear space added outside it.
 *
 * The clamp floor is 6.5rem = 104px, comfortably above brand.json's
 * rules.min_mark_px (48px) even at a 320px viewport. */
.lockup__mark {
  --art: clamp(6.5rem, 28vw, 11.25rem);
  box-sizing: content-box;
  width: var(--art);
  padding: calc(var(--art) * 0.25);
  margin: 0 auto;
}

.lockup__mark img {
  width: 100%;
}

/* The wordmark master is baked pixels on its own near-black plate (it is not
 * type, and per brand doctrine it is never re-set or re-spaced). Two things
 * happen here, neither of which touches the artwork:
 *   1. object-fit: cover crops the plate's empty margins to a wide band.
 *      Source is 768x512 with the "VOID CRAFT" glyphs at y 213-267, so a
 *      768x150 band centred at y=239 lands at object-position 50% 45%.
 *      cover preserves the aspect ratio -> no stretch, no shear. The band runs
 *      to y=313, and the derived PNG carries no ink at all below y=267
 *      (verified by scanning the file), so the crop shows the wordmark and
 *      nothing else — in particular it never reveals the master's tagline band.
 *   2. mix-blend-mode: lighten drops the plate (rgb 8,10,16) into the page
 *      ground (rgb 11,13,19) so no rectangle seam shows. Only pixels DARKER
 *      than the page are affected; the silver glyphs are untouched. */
.lockup__wordmark {
  width: min(100%, 28.75rem);
  aspect-ratio: 768 / 150;
  margin: clamp(0.5rem, 2vw, 1rem) auto 0;
  overflow: hidden;
}

.lockup__wordmark img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 45%;
  mix-blend-mode: lighten;
}

/* Studio descriptor under the wordmark.
 *
 * This slot used to read "AI Games" in signal_cyan — the loudest thing on the
 * page. Two reasons it no longer does: the 2026-07-27 brand decision that
 * player-facing surfaces do not lead with "AI", and brand.json's own
 * identity.tagline_shipped = false, which says that tagline is not a shipped
 * surface. It is now a quiet, warm descriptor: soft silver, gentler tracking. */
.lockup__tagline {
  margin-top: 0.9rem;
  font-size: clamp(0.7rem, 2.6vw, 0.82rem);
  letter-spacing: 0.24em;
  text-indent: 0.24em; /* balance the trailing letter-space */
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: 600;
}

.hero__headline {
  margin-top: clamp(1.5rem, 6vw, 2.5rem);
  font-size: clamp(1.7rem, 7.4vw, 3.1rem);
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--ice-white);
  max-width: 17ch;
  text-wrap: balance;
}

.hero__status {
  margin-top: 1.25rem;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 1.05rem;
  border: 1px solid rgba(116, 47, 201, 0.45);
  border-radius: var(--radius-pill);
  background: rgba(51, 20, 85, 0.3);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ice-white);
}

/* A slow, soft breath rather than a hard blinking dot. */
.hero__status::before {
  content: "";
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 50%;
  background: var(--signal-cyan);
  box-shadow: 0 0 0 0 rgba(52, 212, 220, 0.45);
  animation: pulse 3.6s ease-out infinite;
}

@keyframes pulse {
  70% {
    box-shadow: 0 0 0 12px rgba(52, 212, 220, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(52, 212, 220, 0);
  }
}

.hero__lede {
  margin-top: 1.35rem;
  max-width: 42ch;
  font-size: clamp(1rem, 3.6vw, 1.12rem);
  color: var(--silver);
}

.hero__actions {
  margin-top: 1.9rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
  width: 100%;
}

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min); /* comfortable tap target on a phone */
  max-width: 100%;
  padding: 0.7rem 1.5rem;
  border-radius: var(--radius-pill);
  text-decoration: none;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-align: center;
  transition: transform 180ms ease, background-color 180ms ease,
    border-color 180ms ease, color 180ms ease, box-shadow 180ms ease;
}

.btn--primary {
  background: var(--bright-violet);
  color: var(--ice-white);
  border: 1px solid var(--bright-violet);
  /* soft bloom under the button instead of a hard neon rim */
  box-shadow: 0 10px 30px rgba(116, 47, 201, 0.28);
}

.btn--primary:hover {
  background: var(--violet-lift);
  border-color: var(--violet-lift);
  transform: translateY(-1px);
  box-shadow: 0 14px 36px rgba(116, 47, 201, 0.36);
}

.btn--ghost {
  border: 1px solid var(--hairline-strong);
  color: var(--ice-white);
}

.btn--ghost:hover {
  border-color: rgba(116, 47, 201, 0.7);
  background: rgba(116, 47, 201, 0.12);
  transform: translateY(-1px);
}

/* what we're building ------------------------------------------------------ */

.strip {
  padding: 0 var(--gutter) clamp(2.5rem, 9vw, 4.5rem);
}

.strip__list {
  list-style: none;
  margin: 0 auto;
  max-width: var(--page-max);
  display: grid;
  gap: 0.9rem;
  grid-template-columns: 1fr;
}

/* Each card carries its own accent, used only by its little illustration.
 * All three accents are brand tokens; none of them shouts, because the icon is
 * 2.75rem of line art rather than a headline. */
.strip__item {
  --accent: var(--signal-cyan);
  padding: 1.4rem 1.35rem 1.5rem;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-xl);
  background: linear-gradient(
    180deg,
    var(--surface-2) 0%,
    rgba(11, 13, 19, 0.86) 100%
  );
  /* one soft, wide shadow — no rim light */
  box-shadow: 0 18px 40px rgba(11, 13, 19, 0.45);
  transition: transform 220ms ease, border-color 220ms ease,
    box-shadow 220ms ease;
}

.strip__item:nth-child(2) {
  --accent: var(--bright-violet);
}

.strip__item:hover {
  transform: translateY(-3px);
  border-color: rgba(116, 47, 201, 0.4);
  box-shadow: 0 22px 50px rgba(11, 13, 19, 0.55),
    0 0 0 1px var(--glow-violet-faint);
}

/* Inline SVG accent. Self-contained in the HTML — no external asset, no icon
 * font. The outline takes --icon-ink, the one filled shape takes --accent. */
.strip__icon {
  width: 2.75rem;
  height: 2.75rem;
  margin-bottom: 0.9rem;
  color: var(--accent);
  --icon-ink: rgba(229, 229, 229, 0.85);
}

.strip__icon .ink {
  fill: none;
  stroke: var(--icon-ink);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.strip__icon .pop {
  fill: currentColor;
}

.strip__title {
  font-size: 1.08rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--ice-white);
}

.strip__body {
  margin-top: 0.45rem;
  font-size: 0.95rem;
  color: var(--text-soft);
}

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

.site-footer {
  flex: 0 0 auto;
  padding: 1.25rem var(--gutter) 2.25rem;
  border-top: 1px solid rgba(194, 193, 193, 0.1);
  text-align: center;
  font-size: 0.85rem;
  color: var(--text-soft);
}

.site-footer > * + * {
  margin-top: 0.35rem;
}

/* Legal + contact links. Each is a 44px-tall tap target on a phone, which is
 * why they are inline-flex boxes with vertical room rather than bare text. */
.site-footer__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 0.15rem;
}

.site-footer__nav a,
.site-footer__contact a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding-inline: 0.4rem;
  color: var(--ice-white);
  text-decoration: underline;
  text-decoration-color: rgba(116, 47, 201, 0.7);
  text-underline-offset: 4px;
}

.site-footer__nav a:hover,
.site-footer__contact a:hover {
  color: var(--signal-cyan);
  text-decoration-color: var(--signal-cyan);
}

.site-footer__sep {
  color: var(--text-faint);
}

.site-footer__contact {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0 0.25rem;
  color: var(--text-soft);
}

.site-footer__meta {
  font-size: 0.78rem;
  color: var(--text-faint);
}

/* ===========================================================================
 * 360px and up — the standard small phone. Slightly roomier gutter and a hair
 * more space between cards; the layout is still a single column.
 * ======================================================================== */
@media (min-width: 22.5rem) {
  :root {
    --gutter: 1.25rem;
  }

  .strip__list {
    gap: 1rem;
  }
}

/* ===========================================================================
 * 768px and up — tablets and small laptops. The card row goes 3-up, the hero
 * gets more air, and the footer lays its lines out on one row.
 * ======================================================================== */
@media (min-width: 48rem) {
  :root {
    --gutter: 2rem;
  }

  .strip__list {
    grid-template-columns: repeat(3, 1fr);
    gap: 1.15rem;
  }

  .strip__item {
    padding: 1.6rem 1.5rem 1.75rem;
  }

  .hero__lede {
    max-width: 46ch;
  }

  .site-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.25rem 1.5rem;
    padding-bottom: 2.5rem;
  }

  .site-footer > * + * {
    margin-top: 0;
  }
}

/* ===========================================================================
 * 1024px and up — desktop. The page stops growing (--page-max) and the hero
 * takes its last step up; nothing re-flows past this point.
 * ======================================================================== */
@media (min-width: 64rem) {
  .hero {
    padding-top: 6rem;
  }

  .strip__icon {
    width: 3rem;
    height: 3rem;
  }
}

/* Users who asked for less motion get no lift and no pulse. tokens.css already
 * flattens durations; this removes the transforms themselves. */
@media (prefers-reduced-motion: reduce) {
  .btn:hover,
  .strip__item:hover {
    transform: none;
  }

  .hero__status::before {
    animation: none;
  }
}
