/* =============================================================================
   Storefront site styles
   =============================================================================
   Loaded from every page. Imports tokens then defines the site-wide layout
   chrome (header, nav, footer, content max-width). Per-page styles live with
   the page or in the relevant <style> block; this file does NOT carry
   page-specific styling.
   ============================================================================= */

@import url('/packages/shared-ui/src/tokens.css');

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  position: relative;
  isolation: isolate; /* keep ambient layers stacked below content */
}

/* ---------------------------------------------------------------------------
   Ambient: hero radial glow + drifting particle field.
   Inspired by the avaprotocol.org treatment, kept brand-correct (cyan to
   magenta gradient, no third-party feel).
   --------------------------------------------------------------------------- */

body::before {
  /* Hero radial glow. Anchored top-center, fades fast. */
  content: '';
  position: fixed;
  top: -20vh;
  left: 50%;
  width: 110vw;
  max-width: 1400px;
  height: 90vh;
  transform: translateX(-50%);
  background:
    radial-gradient(ellipse 60% 60% at 35% 30%, rgba(0, 240, 255, 0.13), transparent 65%),
    radial-gradient(ellipse 55% 55% at 70% 25%, rgba(255, 45, 209, 0.1), transparent 60%);
  filter: blur(40px);
  pointer-events: none;
  z-index: -2;
}

body::after {
  /* Particle field (small dots in brand-tinted glows) drawn from an SVG. */
  content: '';
  position: fixed;
  inset: 0;
  background-image: url('/static/particles.svg');
  background-size: cover;
  background-position: center;
  opacity: 0.55;
  pointer-events: none;
  z-index: -1;
  animation: particle-drift 28s ease-in-out infinite alternate;
}

@keyframes particle-drift {
  0% {
    transform: translate(0, 0);
  }
  50% {
    transform: translate(12px, -8px);
  }
  100% {
    transform: translate(-10px, 6px);
  }
}

@media (prefers-reduced-motion: reduce) {
  body::after {
    animation: none;
  }
}

main {
  flex: 1;
  width: 100%;
  max-width: 64rem;
  margin: 0 auto;
  padding: var(--space-5) var(--space-4);
}

header.site-header {
  position: sticky;
  top: 0;
  background: rgba(10, 10, 15, 0.85);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
  padding: var(--space-3) var(--space-4);
  z-index: var(--z-overlay);
}

.site-header .row {
  max-width: 64rem;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: -0.02em;
}

.brand:hover,
.brand:focus-visible {
  text-decoration: none;
  color: var(--text-primary);
}

.brand .logo {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
}

nav.primary {
  display: flex;
  gap: var(--space-3);
  margin-left: auto;
}

nav.primary a {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: var(--font-size-sm);
}

nav.primary a:hover,
nav.primary a:focus-visible,
nav.primary a[aria-current='page'] {
  color: var(--text-primary);
  background: var(--bg-elevated);
  text-decoration: none;
}

footer.site-footer {
  border-top: 1px solid var(--border);
  padding: var(--space-5) var(--space-4);
  /* Honor the device safe areas so the footer clears the home indicator and
     side notches in an installed PWA; falls back to 0 in a normal browser. */
  padding-right: max(var(--space-4), env(safe-area-inset-right, 0px));
  padding-bottom: max(var(--space-5), env(safe-area-inset-bottom, 0px));
  padding-left: max(var(--space-4), env(safe-area-inset-left, 0px));
  color: var(--text-muted);
  font-size: var(--font-size-sm);
}

footer.site-footer .row {
  max-width: 64rem;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: space-between;
  align-items: center;
}

footer.site-footer a {
  color: var(--text-secondary);
}

footer.site-footer .accept-notice {
  font-size: var(--font-size-xs);
  color: var(--text-muted);
  font-family: var(--font-mono);
}

footer.site-footer .accept-notice a {
  color: var(--text-muted);
  text-decoration: underline;
}

/* Used in footers for the "manage privacy" affordance: looks like a link
   but is a real button so it can open the consent banner. */
.link-btn {
  background: transparent;
  border: 0;
  color: var(--text-secondary);
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
  font: inherit;
  min-height: 0;
}
.link-btn:hover,
.link-btn:focus-visible {
  color: var(--text-primary);
}

.hero {
  padding: var(--space-10) 0 var(--space-6);
  text-align: left;
  position: relative;
}

.hero h1 {
  font-size: clamp(2.4rem, 7vw, 4rem);
  line-height: 1.05;
  margin: 0 0 var(--space-4);
  letter-spacing: -0.025em;
  font-weight: 700;
}

.hero h1 .accent {
  background: var(--brand-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero p.tagline {
  color: var(--text-secondary);
  font-size: var(--font-size-lg);
  max-width: 38rem;
  margin: 0 0 var(--space-6);
}

.hero .cta-row {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.btn-primary {
  background: var(--brand-gradient);
  color: #0a0a0f;
  border: none;
  font-weight: 600;
  box-shadow:
    0 0 0 1px rgba(0, 240, 255, 0.25),
    0 6px 24px -6px rgba(0, 240, 255, 0.45),
    0 6px 24px -6px rgba(255, 45, 209, 0.35);
  transition:
    filter var(--duration-medium) var(--ease-emphasized),
    box-shadow var(--duration-medium) var(--ease-emphasized),
    transform var(--duration-fast) var(--ease-emphasized);
}

.btn-primary:hover,
.btn-primary:focus-visible {
  filter: brightness(1.08);
  box-shadow:
    0 0 0 1px rgba(0, 240, 255, 0.4),
    0 10px 32px -6px rgba(0, 240, 255, 0.55),
    0 10px 32px -6px rgba(255, 45, 209, 0.45);
  transform: translateY(-1px);
}

.btn-ghost {
  background: transparent;
  border: 1px solid var(--border);
  transition:
    border-color var(--duration-medium) var(--ease-emphasized),
    transform var(--duration-fast) var(--ease-emphasized);
}

.btn-ghost:hover,
.btn-ghost:focus-visible {
  border-color: var(--accent-cyan);
  transform: translateY(-1px);
}

.section-h2 {
  font-size: var(--font-size-xl);
  margin: var(--space-8) 0 var(--space-4);
  letter-spacing: -0.01em;
}

.game-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
}

.game-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background: rgba(19, 19, 25, 0.7);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  text-decoration: none;
  color: inherit;
  transition:
    border-color var(--duration-medium) var(--ease-emphasized),
    transform var(--duration-medium) var(--ease-emphasized),
    box-shadow var(--duration-medium) var(--ease-emphasized);
  position: relative;
  overflow: hidden;
}

.game-card::before {
  /* Soft accent halo on hover, color depends on data-accent. */
  content: '';
  position: absolute;
  inset: -40%;
  background: radial-gradient(
    circle at 50% 0%,
    color-mix(in srgb, var(--accent, var(--accent-cyan)) 30%, transparent),
    transparent 70%
  );
  opacity: 0;
  transition: opacity var(--duration-medium) var(--ease-emphasized);
  pointer-events: none;
  z-index: -1;
}

.game-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: 0 12px 32px -12px
    color-mix(in srgb, var(--accent, var(--accent-cyan)) 50%, transparent);
  text-decoration: none;
}

.game-card:hover::before {
  opacity: 1;
}

.game-card[data-accent='lime'] {
  --accent: var(--accent-lime);
}
.game-card[data-accent='magenta'] {
  --accent: var(--accent-magenta);
}
.game-card[data-accent='cyan'] {
  --accent: var(--accent-cyan);
}

.game-card .badge {
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  color: var(--accent, var(--text-secondary));
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.game-card h3 {
  margin: 0;
  font-size: var(--font-size-lg);
  letter-spacing: -0.01em;
}

.game-card p {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--font-size-sm);
}

.game-card .status {
  margin-top: auto;
  font-size: var(--font-size-xs);
  color: var(--text-muted);
}

.surface-prose {
  max-width: 38rem;
}

.surface-prose p {
  color: var(--text-secondary);
}

.skip-link {
  position: absolute;
  top: -40px;
  left: var(--space-3);
  background: var(--bg-elevated);
  border: 1px solid var(--accent-cyan);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  z-index: var(--z-modal);
}

.skip-link:focus {
  top: var(--space-3);
}

/* ---------------------------------------------------------------------------
   Wave divider between sections (avaprotocol-inspired). Inline SVG via
   data URI so we don't need a network request.
   --------------------------------------------------------------------------- */
.section-divider {
  display: block;
  width: 100%;
  height: 64px;
  margin: var(--space-6) 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 64' preserveAspectRatio='none'><path d='M0,32 C200,8 400,56 600,32 C800,8 1000,56 1200,32 L1200,64 L0,64 Z' fill='%2300f0ff' fill-opacity='0.06'/><path d='M0,40 C220,16 440,64 660,40 C880,16 1100,64 1200,40 L1200,64 L0,64 Z' fill='%23ff2dd1' fill-opacity='0.05'/></svg>");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  pointer-events: none;
}

.section-h2 {
  position: relative;
  font-size: var(--font-size-xl);
  margin: var(--space-8) 0 var(--space-4);
  letter-spacing: -0.01em;
  display: inline-block;
}

.section-h2::after {
  /* Tiny accent rule under the heading to echo the brand gradient. */
  content: '';
  position: absolute;
  left: 0;
  bottom: -6px;
  width: 2.4rem;
  height: 2px;
  background: var(--brand-gradient);
  border-radius: 2px;
}

/* ---------------------------------------------------------------------------
   Surface-prose: lighten the typography so long-form pages (privacy / terms /
   about) feel less like a wall of text on the new ambient background.
   --------------------------------------------------------------------------- */
.surface-prose h2 {
  margin-top: var(--space-6);
  font-size: var(--font-size-lg);
  letter-spacing: -0.01em;
}

.surface-prose h3 {
  margin-top: var(--space-5);
  font-size: var(--font-size-md);
  letter-spacing: -0.005em;
  color: var(--text-primary);
}

.surface-prose ul {
  padding-left: 1.25rem;
  color: var(--text-secondary);
}

.surface-prose li {
  margin: 0.25rem 0;
}

.surface-prose code {
  font-family: var(--font-mono);
  font-size: 0.95em;
  background: rgba(28, 28, 36, 0.7);
  padding: 0.05rem 0.35rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}

/* ---------------------------------------------------------------------------
   Immersive play: while a game is live its mount fills the viewport and page
   scroll is locked, so an accidental scroll or swipe can't disrupt play.
   Toggled by /packages/shared-ui/src/immersive-play.js, which watches the
   game overlay's [hidden] state (overlay hidden == game running). Exit with
   the Esc key or the on-screen button. The game is centered and clamped to the
   viewport rather than force-stretched, so every game's own layout stays sane.
   --------------------------------------------------------------------------- */
body.ns-immersive {
  overflow: hidden;
  /* While a game is live there is nothing to scroll, so surrender every browser
     touch gesture: no double-tap zoom, no pinch zoom, no rubber-band scroll.
     Pointer events still fire, so the NERD pad keeps working. This is what stops
     a stray double-tap (e.g. mashing a button) from zooming the arena. */
  touch-action: none;
  overscroll-behavior: none;
}

body.ns-immersive .ns-immersive-target {
  position: fixed;
  inset: 0;
  touch-action: none;
  /* dvw/dvh follow the *current* viewport as mobile browser chrome shows and
     hides, so the game truly fills the screen on iOS Safari (no Fullscreen API
     there) and Android Chrome alike. Older engines fall back to vw/vh. */
  width: 100vw;
  height: 100vh;
  width: 100dvw;
  height: 100dvh;
  z-index: 400; /* above header (100), modal (200), toast (300) */
  margin: 0;
  padding: 0;
  max-width: none;
  background: #0a0a0f;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

body.ns-immersive .ns-immersive-target > * {
  margin: 0;
  max-width: 100dvw;
  max-height: 100dvh;
}

.ns-immersive-exit {
  position: fixed;
  top: env(safe-area-inset-top, 0px);
  right: env(safe-area-inset-right, 0px);
  margin: var(--space-3);
  z-index: 401;
  font-family: var(--font-mono);
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  background: rgba(10, 10, 15, 0.75);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
}

.ns-immersive-exit:hover,
.ns-immersive-exit:focus-visible {
  color: var(--text-primary);
  border-color: var(--accent-cyan);
}

/* ---------------------------------------------------------------------------
   Orientation nudge: on a phone held upright, action games play far better
   sideways. mobile-play.js injects this node into the game overlay, just above
   the play / play-again button. It only paints on a touch device in portrait;
   the moment the phone turns landscape (or on any mouse device) it collapses to
   nothing. Pure CSS visibility: no JS state to keep in sync.
   --------------------------------------------------------------------------- */
.ns-rotate-nudge {
  display: none;
}

@media (pointer: coarse) and (orientation: portrait) {
  .ns-rotate-nudge {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    margin: 0 auto var(--space-3);
    padding: var(--space-3) var(--space-4);
    max-width: 22rem;
    text-align: center;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
  }
}

/* the phone: a rounded rect with a screen, rotating from upright to sideways */
.ns-rotate-phone {
  width: 34px;
  height: 58px;
  border: 2px solid var(--accent-cyan);
  border-radius: 7px;
  position: relative;
  transform-origin: 50% 50%;
  animation: ns-rotate-phone 2.4s ease-in-out infinite;
}

.ns-rotate-phone::before {
  /* the screen */
  content: '';
  position: absolute;
  inset: 5px 4px;
  border-radius: 2px;
  background: rgba(56, 189, 248, 0.22);
}

.ns-rotate-phone::after {
  /* the home button / speaker dot */
  content: '';
  position: absolute;
  bottom: 2px;
  left: 50%;
  width: 6px;
  height: 2px;
  transform: translateX(-50%);
  border-radius: 2px;
  background: var(--accent-cyan);
}

.ns-rotate-nudge p {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

@keyframes ns-rotate-phone {
  0%,
  28% {
    transform: rotate(0deg);
  }
  60%,
  100% {
    transform: rotate(-90deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ns-rotate-phone {
    animation: none;
    transform: rotate(-90deg); /* show the goal state, no spin */
  }
}

/* ---------------------------------------------------------------------------
   Orientation lock: action games require landscape. immersive-play.js drops
   this full-viewport curtain into the body on every game page; CSS reveals it
   only on a touch device held in portrait, where it covers the game and its
   controls entirely. The game is paused underneath (immersive-play.js fires an
   orientation event the game listens for), so nothing advances while the curtain
   is up. Turn the phone sideways and it collapses to nothing. Inert on desktop.
   --------------------------------------------------------------------------- */
.ns-rotate-lock {
  display: none;
}

@media (pointer: coarse) and (orientation: portrait) {
  .ns-rotate-lock {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 500; /* above the gamepad (402), exit (401), immersive layer (400) */
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-5);
    text-align: center;
    background: var(--bg-base, #0a0a0f);
  }
}

.ns-rotate-lock p {
  margin: 0;
  max-width: 22rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-md);
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------------
   Frosted-glass gamepad: the one on-screen controller for every action game on
   touch. Built by /packages/shared-ui/src/gamepad.js. A thumb joystick pins to
   the bottom-left, a four-button diamond labeled N E R D (our XYBA) to the
   bottom-right, like a console pad. The stick reports the eight directions as
   the old D-pad did (up/down/left/right, 8-way with diagonals); the faces stay
   momentary buttons (n/e/r/d). Each game maps those actions to its own moves.
   Visible only while a game is live (body.ns-immersive) on a coarse pointer;
   mouse + keyboard never see it.
   --------------------------------------------------------------------------- */
.ns-gamepad {
  display: none;
}

@media (pointer: coarse) {
  body.ns-immersive .ns-gamepad {
    display: flex;
    position: fixed;
    inset: auto 0 0 0;
    z-index: 402; /* above the immersive layer (400) and exit button (401) */
    justify-content: space-between;
    align-items: flex-end;
    padding: 0 max(var(--space-3), env(safe-area-inset-right, 0px)) max(var(--space-4), env(safe-area-inset-bottom, 0px))
      max(var(--space-3), env(safe-area-inset-left, 0px));
    pointer-events: none; /* the gap between clusters lets taps fall through */
  }
}

/* The face cluster is a 3x3 grid; the four buttons sit in the edge cells to
   form a diamond, the center cell left empty. */
.ns-gamepad-cluster {
  pointer-events: auto;
  display: grid;
  grid-template-columns: repeat(3, var(--ns-pad-size, 3.4rem));
  grid-template-rows: repeat(3, var(--ns-pad-size, 3.4rem));
  gap: 0.4rem;
}

.ns-pad-btn {
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
  user-select: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  min-width: var(--hit-target-min);
  min-height: var(--hit-target-min);
  font-family: var(--font-mono);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-primary);
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(20, 20, 30, 0.35);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}

/* Thumb joystick: a frosted ring (base) with a draggable nub. The base owns one
   pointer; dragging the nub points the thumb at a direction. gamepad.js moves
   the nub via transform and translates the thumb vector into 8-way directions. */
.ns-joystick {
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
  user-select: none;
  position: relative;
  width: var(--ns-stick-size, 9.5rem);
  height: var(--ns-stick-size, 9.5rem);
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(20, 20, 30, 0.3);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: inset 0 0 24px rgba(0, 0, 0, 0.35);
  display: grid;
  place-items: center;
}
.ns-joystick.is-active {
  border-color: rgba(56, 189, 248, 0.55);
}
.ns-joystick-nub {
  width: 42%;
  height: 42%;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(56, 189, 248, 0.28);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4);
  transition: transform 60ms ease-out;
  will-change: transform;
}
.ns-joystick.is-active .ns-joystick-nub {
  background: rgba(56, 189, 248, 0.45);
  border-color: var(--accent-cyan);
}

/* NERD diamond: N left, E top, R right, D bottom. */
.ns-pad-btn.face-e {
  grid-column: 2;
  grid-row: 1;
}
.ns-pad-btn.face-n {
  grid-column: 1;
  grid-row: 2;
}
.ns-pad-btn.face-r {
  grid-column: 3;
  grid-row: 2;
}
.ns-pad-btn.face-d {
  grid-column: 2;
  grid-row: 3;
}

.ns-pad-btn.is-down {
  background: rgba(56, 189, 248, 0.32);
  border-color: var(--accent-cyan);
}

/* A lone action button (a platformer's JUMP, a shooter's FIRE): one circle,
   centered, sized a touch larger than a diamond face, with room for a word. */
.ns-gamepad-cluster.is-solo {
  grid-template-columns: none;
  grid-template-rows: none;
  place-items: center;
}
.ns-gamepad-cluster.is-solo .ns-pad-btn {
  width: var(--ns-solo-size, 4.6rem);
  height: var(--ns-solo-size, 4.6rem);
  font-size: 0.8rem;
  letter-spacing: 0.05em;
}

/* The shared NERD pad is now the one controller for every action game, so the
   old per-game touch button strips are retired. Hidden, not deleted: their
   markup and listeners stay inert behind the joystick. */
.ff-touch,
.dh-touch,
.so-touch,
.sc-touch,
.rc-touch {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .ns-pad-btn {
    transition: none;
  }
}
