/* ============================================
   TypeBlocks - Base
   Reset, page scaffold, utilities, accessibility.
   Loads after tokens.css, before style.css.
   ============================================ */

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  --stage-pulse: 0;
  --stage-atmosphere-opacity: 0.34;
  --stage-atmosphere-pulse: 0;
  --stage-horizon-opacity: 0.2;
  --stage-horizon-pulse: 0;
  --stage-caustic-shift: 0px;
  --stage-caustic-lift: 0px;
  --stage-caustic-scale-low: 1.02;
  --stage-caustic-scale-mid: 1.04;
  --stage-caustic-scale-high: 1.025;
  --stage-wave-shift: 0px;
  --stage-wave-lift: 0px;
  --stage-wave-scale-low: 0.9;
  --stage-wave-scale-high: 1.08;
  background: var(--color-bg);
  background-image: var(--color-bg-gradient);
  color: var(--color-text);
  font-family: var(--font-sans);
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  overflow-x: hidden;
  overflow-y: auto;
  position: relative;
  isolation: isolate;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body::before,
body::after {
  content: "";
  position: fixed;
  pointer-events: none;
  z-index: 0;
}

body::before {
  inset: -16vmax;
  opacity: calc(var(--stage-atmosphere-opacity) + var(--stage-atmosphere-pulse));
  background-image:
    linear-gradient(115deg,
      transparent 0%,
      transparent 34%,
      color-mix(in srgb, var(--color-primary) 12%, transparent) 43%,
      transparent 56%),
    linear-gradient(245deg,
      transparent 0%,
      transparent 42%,
      color-mix(in srgb, var(--color-accent-2) 9%, transparent) 53%,
      transparent 66%),
    repeating-linear-gradient(90deg,
      color-mix(in srgb, var(--color-primary) 10%, transparent) 0 1px,
      transparent 1px 104px),
    repeating-linear-gradient(0deg,
      color-mix(in srgb, var(--color-accent-2) 7%, transparent) 0 1px,
      transparent 1px 118px);
  background-position:
    0% 50%,
    100% 42%,
    0 0,
    0 0;
  background-size:
    190% 190%,
    170% 170%,
    104px 118px,
    104px 118px;
  animation: stage-atmosphere-drift 38s linear infinite;
  transition: opacity 90ms linear;
}

body::after {
  left: -12vw;
  right: -12vw;
  bottom: -8vh;
  height: 46vh;
  opacity: calc(var(--stage-horizon-opacity) + var(--stage-horizon-pulse));
  background-image:
    linear-gradient(180deg,
      transparent 0%,
      color-mix(in srgb, var(--color-primary) 11%, transparent) 42%,
      transparent 78%),
    repeating-linear-gradient(90deg,
      transparent 0 72px,
      color-mix(in srgb, var(--color-primary) 12%, transparent) 72px 73px);
  transform-origin: 50% 100%;
  animation: stage-horizon-breathe 14s ease-in-out infinite alternate;
  transition: opacity 120ms linear;
}

/* Drift via transform ONLY (compositor-accelerated). This used to also animate
   background-position across four gradient layers on the full-viewport ::before,
   which repainted the whole layer every frame and blew the camera frame budget
   (mean ~27ms vs the 20ms gate — visual.spec 141/356 failed, CI red on main).
   The translate/scale here already carries the drifting motion at zero paint
   cost; the only loss is faint inter-layer parallax, imperceptible at this
   layer's 0.34 opacity. */
@keyframes stage-atmosphere-drift {
  0% {
    transform: translate3d(-1.4vw, -0.8vh, 0) scale(1.02);
  }

  50% {
    transform: translate3d(0.8vw, 0.4vh, 0) scale(1.025);
  }

  100% {
    transform: translate3d(1.4vw, 0.8vh, 0) scale(1.02);
  }
}

@keyframes stage-horizon-breathe {
  0% {
    transform: translate3d(-2vw, 0, 0) skewX(-4deg) scaleY(0.94);
  }

  100% {
    transform: translate3d(2vw, -1vh, 0) skewX(4deg) scaleY(1.08);
  }
}

body[data-theme="contrast"]::before,
body[data-theme="contrast"]::after {
  --stage-atmosphere-opacity: 0.06;
  --stage-horizon-opacity: 0.06;
}

/* Game Container */
#game-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  position: relative;
  width: 100%;
  max-width: 650px;
  min-height: 100vh;
  min-height: 100dvh;
  justify-content: center;
  margin: 0 auto;
  padding: clamp(12px, 3vh, 20px);
  z-index: 1;
}

/* ============================================
   UTILITY CLASSES
   ============================================ */

.hidden {
  display: none !important;
}

/* ============================================
   ACCESSIBILITY
   ============================================ */

/* Visible focus rings for keyboard navigation */
button:focus-visible,
input:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Respect users who prefer reduced motion: everything resolves
   instantly (zero delay too, so staggered cards never blink in late) */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }
}
