/* ════════════════════════════════════════════════════════════════════
 *  TYGRA · THE FERAL QUEEN — endless-runner landing page.
 *
 *  Vanilla CSS. The jungle scrolls past Tygra (parallax layers at
 *  different speeds). Tygra stays centred, bobs in a run cycle, jumps
 *  on input. Single static character sprite — JS chroma-keys the JPG
 *  and draws it to a canvas so she layers over the jungle.
 *
 *  Time-of-day is driven by `data-time` on <html>:
 *     "dawn" · "day" · "dusk" · "night"
 *  All ambient colours read from CSS variables. One attribute flip
 *  re-skins the whole scene.
 * ════════════════════════════════════════════════════════════════════ */

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

:root {
  --c-jungle-deep:  #0a1610;
  --c-jungle-mid:   #1a3a25;
  --c-jungle-light: #2d5f3e;
  --c-canopy:       #16301f;
  --c-stone:        #4a4239;
  --c-stone-light:  #6b5f4d;
  --c-gold:         #d4a056;
  --c-gold-deep:    #b8732e;
  --c-crimson:      #8b2e1f;
  --c-bone:         #f4e0c4;

  /* Default = dusk */
  --sky-top:   #2a1f3a;
  --sky-mid:   #5e3a4a;
  --sky-low:   #c87850;
  --sun-x:     78%;
  --sun-y:     58%;
  --sun-op:    0.85;
  --moon-op:   0;
  --stars-op:  0.15;
  --rim-light: #f4d4a8;
  --rim-intensity: 0.55;
  --canopy-shade:   #0a1810;
  --fog-intensity:  0.18;
  --ambient-tint:   rgba(212, 160, 86, 0.06);
  --vignette-deep:  0.55;
}

html[data-time="dawn"] {
  --sky-top:   #1a2540;
  --sky-mid:   #b89090;
  --sky-low:   #f4d4a8;
  --sun-x:     88%; --sun-y: 72%; --sun-op: 1; --moon-op: 0; --stars-op: 0;
  --rim-light: #ffd49a; --rim-intensity: 0.7;
  --canopy-shade: #1a2818; --fog-intensity: 0.28;
  --ambient-tint: rgba(255, 200, 140, 0.05); --vignette-deep: 0.40;
}
html[data-time="day"] {
  --sky-top:   #4a8fb8;
  --sky-mid:   #8ec0d8;
  --sky-low:   #d4e8f0;
  --sun-x:     50%; --sun-y: 22%; --sun-op: 1; --moon-op: 0; --stars-op: 0;
  --rim-light: #fff8e0; --rim-intensity: 0.40;
  --canopy-shade: #1f3525; --fog-intensity: 0.10;
  --ambient-tint: rgba(255, 255, 220, 0.04); --vignette-deep: 0.30;
}
html[data-time="night"] {
  --sky-top:   #060812;
  --sky-mid:   #0e1428;
  --sky-low:   #1a2540;
  --sun-x:     50%; --sun-y: 20%; --sun-op: 0; --moon-op: 0.95; --stars-op: 1;
  --rim-light: #8fa8d8; --rim-intensity: 0.65;
  --canopy-shade: #050a08; --fog-intensity: 0.25;
  --ambient-tint: rgba(60, 90, 160, 0.10); --vignette-deep: 0.75;
}

body {
  font-family: 'Fraunces', Georgia, serif;
  color: var(--c-bone);
  background: var(--c-jungle-deep);
  overflow-x: hidden;
  min-height: 100vh;
}

/* Time-of-day morph — extended to 2.8s with ease-in-out so dawn → day
   etc. transitions feel cinematic, not jumpy. Also tints background-color
   and color for elements that have them. */
.layer-sky, .celestial-sun, .celestial-moon, .celestial-stars,
.layer-mountains svg, .layer-mist, .layer-far-canopy, .layer-midground,
.layer-ground, .character-glow, .layer-foreground, .vignette, .fireflies {
  transition:
    background        2.8s ease-in-out,
    background-color  2.8s ease-in-out,
    color             2.8s ease-in-out,
    fill              2.8s ease-in-out,
    opacity           2.8s ease-in-out,
    filter            2.8s ease-in-out,
    box-shadow        2.8s ease-in-out;
}

/* ── The scene container ─────────────────────────────────────────────── */

.scene {
  position: relative;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  background: var(--c-jungle-deep);
  user-select: none;
  cursor: pointer;
  outline: none;
}
.scene:focus { outline: none; }

.layer { position: absolute; inset: 0; pointer-events: none; }

/* ── Sky + celestials ────────────────────────────────────────────────── */

.layer-sky {
  background: linear-gradient(to bottom,
    var(--sky-top) 0%, var(--sky-mid) 50%, var(--sky-low) 100%);
}

.celestial { position: absolute; inset: 0; pointer-events: none; }
.celestial-sun, .celestial-moon {
  position: absolute;
  left: var(--sun-x); top: var(--sun-y);
  width: 64px; height: 64px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
.celestial-sun {
  background: radial-gradient(circle, #fff8d4 0%, #ffd96b 55%, transparent 75%);
  box-shadow:
    0 0 80px 20px rgba(255, 220, 130, 0.45),
    0 0 200px 50px rgba(255, 200, 100, 0.25);
  opacity: var(--sun-op);
}
.celestial-moon {
  background: radial-gradient(circle at 35% 35%, #f4f0e0 0%, #b8b0a0 60%, transparent 80%);
  box-shadow:
    0 0 50px 10px rgba(200, 215, 255, 0.30),
    0 0 100px 20px rgba(180, 200, 240, 0.18);
  opacity: var(--moon-op);
  left: 78%; top: 18%;
}
.celestial-stars { position: absolute; inset: 0; opacity: var(--stars-op); }
.star {
  position: absolute;
  width: 2px; height: 2px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 0 4px 1px rgba(255,255,255,0.6);
  animation: twinkle var(--dur, 3s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}
@keyframes twinkle {
  0%, 100% { opacity: 0.30; transform: scale(1); }
  50%      { opacity: 1.00;  transform: scale(1.4); }
}

/* ── Mist ────────────────────────────────────────────────────────────── */

.layer-mist {
  background: linear-gradient(to bottom,
    transparent 0%,
    rgba(240, 230, 210, calc(var(--fog-intensity) * 1.2)) 30%,
    rgba(240, 230, 210, var(--fog-intensity)) 50%,
    transparent 70%);
  bottom: 40%; top: 35%; height: auto;
}

/* ── Scrolling tracks — the core of the running effect ───────────────── */
/* Each parallax layer holds a `layer-scroll-track` which is twice as wide
 * as the viewport and contains two identical copies of its content. JS
 * translates the track leftward; when it has scrolled one width's worth,
 * we reset the transform to 0 — the seam is invisible because the two
 * copies are identical. */

.layer-scroll {
  overflow: hidden;
}
.layer-scroll-track {
  position: absolute;
  top: 0; bottom: 0;
  left: 0;
  width: 200%;
  display: flex;
  flex-direction: row;
  will-change: transform;
}

/* ── Mountains ───────────────────────────────────────────────────────── */

.layer-mountains {
  bottom: 40%; top: auto; height: 25%;
}
.layer-mountains .layer-scroll-track > svg {
  flex: 0 0 50%;
  width: 50%; height: 100%; display: block;
}
.layer-mountains polygon {
  fill: var(--canopy-shade);
  opacity: 0.45;
}

/* ── Far canopy ──────────────────────────────────────────────────────── */

.layer-far-canopy {
  bottom: 30%; top: auto; height: 18%;
}
.far-tree-row {
  flex: 0 0 50%;
  display: flex;
  align-items: flex-end;
  justify-content: space-around;
  height: 100%;
}
.far-tree {
  width: 90px;
  height: var(--h);
  background: var(--canopy-shade);
  opacity: 0.65;
  /* Rounded, organic canopy silhouette — many vertices for a cloud-like
     edge that reads as broadleaf jungle vegetation, not conifer. */
  clip-path: polygon(
    50% 0%, 60% 2%, 70% 5%, 80% 10%, 88% 18%, 95% 28%, 98% 40%,
    100% 52%, 95% 65%, 88% 75%, 78% 85%, 65% 92%, 55% 96%,
    50% 100%, 45% 96%, 35% 92%, 22% 85%, 12% 75%, 5% 65%, 0% 52%,
    2% 40%, 5% 28%, 12% 18%, 20% 10%, 30% 5%, 40% 2%
  );
}

/* ── Midground ───────────────────────────────────────────────────────── */

.layer-midground {
  bottom: 0; top: auto; height: 75%;
}
.mid-tree-row {
  flex: 0 0 50%;
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: space-around;
  height: 100%;
}
/* Default mid-tree = broadleaf jungle tree. Wider, rounded canopy with
   a visible trunk underneath — reads as banyan / mango / fig, not pine. */
.mid-tree {
  position: relative;
  width: 180px;
  height: var(--h);
  background: var(--c-jungle-mid);
  filter: brightness(calc(0.85 + var(--tint, 0) * 0.15));
  opacity: 0.92;
  clip-path: polygon(
    /* Top of canopy — many vertices for an organic edge */
    50% 0%, 60% 2%, 70% 5%, 80% 10%, 88% 18%, 95% 28%, 100% 42%,
    /* Right side of canopy curving down to trunk shoulder */
    98% 52%, 92% 58%, 80% 62%, 65% 64%,
    /* Trunk right edge */
    54% 66%, 54% 100%,
    /* Bottom of trunk + left edge */
    46% 100%, 46% 66%,
    /* Left shoulder back into canopy */
    35% 64%, 20% 62%, 8% 58%, 2% 52%,
    /* Left side of canopy */
    0% 42%, 5% 28%, 12% 18%, 20% 10%, 30% 5%, 40% 2%
  );
}

/* Palm variant — thin trunk with a fan of spiky fronds at the top.
   Apply with class `mid-tree--palm`. */
.mid-tree--palm {
  width: 110px;
  clip-path: polygon(
    /* Center top frond */
    48% 0%, 52% 0%,
    /* Right fronds spreading out */
    62% 8%, 78% 12%, 95% 14%, 100% 22%,
    82% 24%, 65% 22%, 60% 28%,
    /* Right shoulder of crown */
    72% 32%, 60% 36%,
    /* Trunk right */
    54% 40%, 56% 100%,
    /* Trunk bottom-left */
    44% 100%, 46% 40%,
    /* Left shoulder + fronds */
    40% 36%, 28% 32%, 40% 28%, 35% 22%, 18% 24%,
    0% 22%, 5% 14%, 22% 12%, 38% 8%
  );
}
.vine {
  position: relative;
  align-self: flex-start;
  width: 4px;
  height: var(--len);
  background: linear-gradient(to bottom,
    var(--c-jungle-light) 0%, var(--c-jungle-mid) 85%, transparent 100%);
  border-radius: 2px;
  opacity: 0.75;
  transform-origin: top center;
  animation: vine-sway 6s ease-in-out infinite;
  animation-delay: var(--delay);
}
.vine::after {
  content: '';
  position: absolute;
  bottom: -6px; left: 50%;
  width: 16px; height: 12px;
  background: var(--c-jungle-light);
  border-radius: 50%;
  transform: translateX(-50%);
}
@keyframes vine-sway {
  0%, 100% { transform: rotate(-2deg); }
  50%      { transform: rotate(2deg); }
}

/* ── Ground — fastest scroll, gives the sense of "running" ───────────── */

.layer-ground {
  bottom: 0; top: auto; height: 20%;
}
.ground-strip {
  flex: 0 0 50%;
  height: 100%;
  background:
    /* Top sliver — dirt edge */
    linear-gradient(to bottom,
      var(--c-jungle-mid) 0%,
      var(--c-jungle-mid) 8%,
      var(--c-jungle-deep) 12%,
      transparent 12%),
    /* Repeating dirt texture */
    repeating-linear-gradient(90deg,
      var(--c-stone) 0px, var(--c-stone) 32px,
      #3a352c 32px, #3a352c 64px);
  filter: brightness(0.7);
}

/* ── Obstacle action-hint labels — float above approaching obstacles
   and fade out as they reach Tygra. Tell the player what input to use
   (TAP for low, HOLD for high jump). ────────────────────────────────── */

.obstacle-label {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-bottom: 12px;
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
  letter-spacing: 0.15em;
  color: var(--c-bone);
  background: rgba(10, 22, 16, 0.78);
  border: 1px solid var(--c-gold-deep);
  padding: 5px 8px;
  border-radius: 3px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;             /* JS fades it in as obstacle approaches */
  transition: opacity 0.15s linear;
  box-shadow: 0 2px 6px rgba(0,0,0,0.5);
  text-transform: uppercase;
}
.obstacle-label::after {
  /* Little tail pointing down at the obstacle, speech-bubble style */
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 4px solid transparent;
  border-top-color: var(--c-gold-deep);
}
.obstacle-label--hold {
  color: var(--c-jungle-deep);
  background: var(--c-gold);
  border-color: var(--c-bone);
}
.obstacle-label--hold::after { border-top-color: var(--c-bone); }

.obstacle-label--danger {
  color: #fff;
  background: rgba(140, 12, 12, 0.92);
  border-color: #ff3030;
  letter-spacing: 0.18em;
  text-shadow: 0 0 8px #ff2020;
  box-shadow:
    0 2px 6px rgba(0,0,0,0.5),
    0 0 12px rgba(255, 30, 30, 0.55);
  animation: label-danger-pulse 0.55s ease-in-out infinite;
}
.obstacle-label--danger::after { border-top-color: #ff3030; }
@keyframes label-danger-pulse {
  0%, 100% { transform: translateX(-50%) scale(1.00); }
  50%      { transform: translateX(-50%) scale(1.10); }
}

@media (max-width: 540px) {
  .obstacle-label { font-size: 7px; padding: 3px 6px; margin-bottom: 8px; }
}

/* ── Obstacles (logs that scroll past) ───────────────────────────────── */

.obstacles {
  position: absolute;
  bottom: 14%;
  left: 0; right: 0;
  height: 60px;
  /* Bumped above the character (z-index: 5) so obstacles — especially
     tall ones like the Shadow Predator — are visible when they pass
     through Tygra's silhouette zone. Without this, the predator spawns
     and reaches collision while completely hidden behind Tygra. */
  z-index: 8;
  pointer-events: none;
  overflow: visible;
}
/* Default obstacle = log (type-log). Subsequent .obstacle.type-* rules
   override sizing + drawing for each variant. */
.obstacle {
  position: absolute;
  bottom: 0;
  width: 60px;
  height: 28px;
  will-change: transform;
}

/* ─── LOG (default) ─────────────────────────────────────────────────── */
.obstacle.type-log {
  background: linear-gradient(to bottom,
    #6b4a2a 0%, #4a3018 50%, #2e1d0e 100%);
  border-top: 2px solid #8b6a3e;
  border-radius: 4px;
  box-shadow:
    inset 0 -3px 0 rgba(0,0,0,0.5),
    0 4px 8px rgba(0,0,0,0.4);
}
.obstacle.type-log::before,
.obstacle.type-log::after {
  content: '';
  position: absolute;
  top: 2px;
  width: 16px; height: 16px;
  background: radial-gradient(circle at center,
    #8b6a3e 0%, #6b4a2a 40%, #4a3018 70%);
  border-radius: 50%;
}
.obstacle.type-log::before { left: 4px; }
.obstacle.type-log::after  { right: 4px; }

/* ─── ROCK — taller, narrower, demands precise jump ─────────────────── */
.obstacle.type-rock {
  width: 48px;
  height: 44px;
  background: linear-gradient(155deg, #8a8580 0%, #5a5552 45%, #2e2a28 100%);
  border-top: 2px solid #aaa5a0;
  border-radius: 50% 50% 30% 30% / 60% 60% 35% 35%;
  box-shadow:
    inset -3px -4px 0 rgba(0,0,0,0.4),
    0 4px 8px rgba(0,0,0,0.5);
}
.obstacle.type-rock::before {
  content: '';
  position: absolute;
  top: 8px;
  left: 14px;
  width: 8px; height: 4px;
  background: #6a6360;
  border-radius: 50%;
  opacity: 0.6;
}

/* ─── THORN PATCH — wider but low ───────────────────────────────────── */
.obstacle.type-thorns {
  width: 95px;
  height: 18px;
  background: linear-gradient(to bottom, #2d5f3e 0%, #1a3a25 100%);
  border-radius: 3px;
  box-shadow:
    inset 0 -2px 0 rgba(0,0,0,0.4),
    0 4px 6px rgba(0,0,0,0.4);
}
.obstacle.type-thorns::before {
  /* Five crimson triangle spikes across the top */
  content: '';
  position: absolute;
  top: -12px;
  left: 0; right: 0;
  height: 14px;
  background: var(--c-crimson);
  clip-path: polygon(
    0 100%, 10% 0, 20% 100%, 30% 0, 40% 100%, 50% 0,
    60% 100%, 70% 0, 80% 100%, 90% 0, 100% 100%
  );
}
.obstacle.type-thorns::after {
  /* Darker base shadow line for depth */
  content: '';
  position: absolute;
  top: -2px;
  left: 0; right: 0;
  height: 3px;
  background: #16301f;
}

/* ─── SNAKE — slithering, animated body with bright contrast ────────── */
.obstacle.type-snake {
  width: 120px;
  height: 38px;
  background:
    /* Dark diagonal banding for that "venomous serpent" pattern */
    repeating-linear-gradient(72deg,
      transparent 0px, transparent 12px,
      rgba(0, 0, 0, 0.32) 12px, rgba(0, 0, 0, 0.32) 16px),
    /* Bright vivid green base — pops against the jungle */
    linear-gradient(to bottom,
      #b8e94a 0%,    /* highlight ridge */
      #6abb3a 25%,
      #3d8a2a 60%,
      #1a4a18 100%);
  border-radius: 60% 35% 35% 60% / 60% 50% 50% 60%;
  border-top: 3px solid #d4f08a;
  box-shadow:
    0 0 14px rgba(106, 219, 74, 0.55),       /* greenish outer glow */
    inset 0 -3px 0 rgba(0, 0, 0, 0.35),
    inset 0 0 0 1px rgba(212, 240, 138, 0.4);
  /* NOTE: snake-slither animation removed (same bug as the predator —
     animating `transform` on the main obstacle element fought with the
     JS-driven `translate3d()` and kept her stuck at her spawn corner).
     The eye + tongue ::before/::after animations are unaffected because
     pseudo-elements have their own transform contexts. */
}

/* Bigger, glowing, pulsing eye — unmistakable */
.obstacle.type-snake::before {
  content: '';
  position: absolute;
  top: 8px;
  right: 14px;
  width: 7px;
  height: 7px;
  background: #ffcc33;
  border-radius: 50%;
  box-shadow:
    0 0 6px #ffaa00,
    0 0 14px rgba(255, 180, 0, 0.7);
  animation: snake-eye 0.7s ease-in-out infinite;
}
@keyframes snake-eye {
  0%, 100% { opacity: 1;    transform: scale(1); }
  50%      { opacity: 0.7;  transform: scale(1.25); }
}

/* Longer forked tongue — clearly visible flickering out */
.obstacle.type-snake::after {
  content: '';
  position: absolute;
  top: 14px;
  right: -14px;
  width: 16px;
  height: 3px;
  background: var(--c-crimson);
  border-radius: 2px;
  box-shadow: 0 0 4px rgba(255, 40, 40, 0.7);
  animation: tongue-flick 0.6s ease-in-out infinite alternate;
}
@keyframes tongue-flick {
  0%   { transform: translateX(0)   scaleX(1); opacity: 1; }
  100% { transform: translateX(3px) scaleX(1.4); opacity: 0.6; }
}

/* ─── THE ANTAGONIST · SHADOW PREDATOR (real PNG sprite) ────────────── */
.obstacle.type-predator {
  width: 170px;
  height: 170px;
  z-index: 8;
  /* No box-shadow / outline — keep her clean. The drop-shadow on the
     <img> child (below) provides only a subtle ground shadow for depth. */
  /* NOTE: prowl animation deliberately not applied here — CSS animations
     on `transform` fight with the JS-driven `translate3d()` scroll. */
}
/* Sprite is now a real <img> child element so file:// loads it reliably
   (CSS background-image can be blocked on some local-protocol setups). */
.obstacle-predator-sprite {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center bottom;
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
  image-rendering: crisp-edges;
  pointer-events: none;
  filter: drop-shadow(0 4px 0 rgba(0, 0, 0, 0.5));
}
@keyframes predator-prowl {
  0%, 100% { transform: translateY(0)    scaleX(1.00); }
  50%      { transform: translateY(-3px) scaleX(0.98); }
}

/* ── Coins ───────────────────────────────────────────────────────────── */

.coins {
  position: absolute;
  bottom: 14%;
  left: 0; right: 0;
  height: 200px;
  /* Above Tygra so coins are always visible (otherwise they vanish behind
     her when at body height). */
  z-index: 9;
  pointer-events: none;
}
.coin {
  position: absolute;
  bottom: 0;
  width: 18px;
  height: 18px;
  background: radial-gradient(circle at 35% 30%,
    #fff8d4 0%, #ffd96b 35%, #d4a056 70%, #8a531f 100%);
  border-radius: 50%;
  box-shadow:
    0 0 8px rgba(212, 160, 86, 0.6),
    inset -2px -2px 0 rgba(0,0,0,0.25);
  will-change: transform;
  animation: coin-spin 0.7s ease-in-out infinite;
}
.coin.collected {
  animation: coin-collect 0.32s ease-out forwards;
  pointer-events: none;
}
@keyframes coin-spin {
  0%, 100% { transform: scaleX(1); }
  50%      { transform: scaleX(0.3); }
}
@keyframes coin-collect {
  0%   { transform: scale(1)   translateY(0); opacity: 1; }
  100% { transform: scale(2.0) translateY(-40px); opacity: 0; }
}

/* ── Combo flash ─────────────────────────────────────────────────────── */

.combo-flash {
  position: absolute;
  top: 28%; left: 50%;
  z-index: 30;
  transform: translate(-50%, -50%);
  pointer-events: none;
  text-align: center;
  text-shadow:
    0 4px 0 #000,
    0 0 28px rgba(212, 160, 86, 0.7);
  animation: combo-pop 0.75s ease-out;
  will-change: transform, opacity;
}
.combo-flash[hidden] { display: none; }
.combo-flash-num {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 44px;
  color: var(--c-gold);
  margin-bottom: 6px;
}
.combo-flash-text {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 14px;
  letter-spacing: 0.3em;
  color: var(--c-bone);
}
@keyframes combo-pop {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
  20%  { opacity: 1; transform: translate(-50%, -50%) scale(1.18); }
  35%  {              transform: translate(-50%, -50%) scale(1.0); }
  100% { opacity: 0; transform: translate(-50%, -70%) scale(1.05); }
}

/* ── Screen shake on hit ─────────────────────────────────────────────── */

.scene.shake {
  animation: scene-shake 0.4s ease-out;
}
@keyframes scene-shake {
  0%, 100% { transform: translate(0, 0); }
  10% { transform: translate(-8px, 2px); }
  20% { transform: translate(7px, -2px); }
  30% { transform: translate(-6px, 3px); }
  40% { transform: translate(5px, -1px); }
  50% { transform: translate(-4px, 2px); }
  60% { transform: translate(3px, -1px); }
  70% { transform: translate(-2px, 1px); }
  80% { transform: translate(1px, 0); }
  90% { transform: translate(-1px, 0); }
}

/* ── The Queen — stays centred, runs in place, jumps on input ────────── */

.character-stage {
  position: absolute;
  bottom: 18%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
}

.character-glow {
  position: absolute;
  bottom: 0;
  width: 200px;
  height: 200px;
  background: radial-gradient(circle,
    rgba(212, 160, 86, calc(0.18 * var(--rim-intensity))) 0%,
    transparent 65%);
  filter: blur(8px);
  pointer-events: none;
  animation: aura-breath 5s ease-in-out infinite;
}
@keyframes aura-breath {
  0%, 100% { opacity: 0.85; transform: scale(1.00); }
  50%      { opacity: 1.00; transform: scale(1.06); }
}

.character-shadow {
  position: absolute;
  bottom: -6px;
  width: 70px;
  height: 11px;
  background: radial-gradient(ellipse at center,
    rgba(0,0,0,0.55) 0%, transparent 70%);
  border-radius: 50%;
  filter: blur(2px);
  /* Matched to the 0.36s sprite-sheet cycle so the shadow pulses in step. */
  animation: shadow-pulse 0.36s ease-in-out infinite;
}

/* Particle canvas — dust at feet + ambient sparks around her aura.
   Sized generously so dust can fan out and sparks can drift up.
   Positioned behind the character img by source order. */
.character-particles {
  position: absolute;
  bottom: -20px;
  left: 50%;
  transform: translateX(-50%);
  width: 480px;
  height: 460px;
  pointer-events: none;
}
@keyframes shadow-pulse {
  0%, 100% { transform: scaleX(1.00); opacity: 0.85; }
  50%      { transform: scaleX(0.78); opacity: 0.5; }
}

/* The canvas. Bobs in a run cycle by default; class .jump overrides
 * with a higher pop animation; class .land does the recovery. */
/* Flip wrapper — mirrors the character horizontally when she's running
 * left. Kept on its own element so the inner .character-canvas keeps its
 * run/jump animation timeline uninterrupted by the direction change. */
.character-flip {
  display: block;
  transform-origin: 50% 100%;
  transition: transform 0.18s ease;
}
.character-flip.face-left {
  transform: scaleX(-1);
}

/* 3-frame sprite-sheet driven character. --frame-w is the SOURCE OF
 * TRUTH for size; everything else (height, background-size, animation
 * end-position) derives from it. Mobile breakpoints just override it. */
.character-canvas {
  --frame-w: min(24vh, 240px);
  position: relative;
  display: block;
  width:  var(--frame-w);
  height: var(--frame-w);
  /* Sprite sheet: 3 horizontal frames. We scale the sheet to (3 × --frame-w)
     so each frame is exactly --frame-w wide in the container. */
  background-image: url('assets/images/tygra-running.png');
  background-size: calc(var(--frame-w) * 3) var(--frame-w);
  background-position: 0 0;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
  image-rendering: crisp-edges;
  filter: drop-shadow(0 4px 0 rgba(0,0,0,0.4));
  /* steps(3, end) holds each frame for 1/3 of the cycle, no interpolation. */
  animation: tygra-run 0.36s steps(3, end) infinite;
  transform-origin: 50% 100%;
}

/* Run cycle — shifts the sheet left by one full sheet-width over the
   animation. With steps(3), the visible held positions are 0, -1×frame,
   -2×frame (= the 3 frames). At t=1 it would be -3×frame but the loop
   wraps before that point. */
@keyframes tygra-run {
  from { background-position-x: 0; }
  to   { background-position-x: calc(var(--frame-w) * -3); }
}

/* Jump is driven by JS physics now (variable height — tap for short hop,
   hold for high jump). JS sets inline `transform: translateY(...)` each
   frame while airborne. The .jump class is still applied as a marker for
   the `isJumping` state and any future jump-only CSS hooks. */
.character-canvas.jump {
  /* Run keyframe continues; transform is JS-owned during jump. */
}

/* Landing squish — JS clears inline transform on touchdown, then this
   animation takes over for 220ms. */
.character-canvas.landed {
  animation:
    tygra-run 0.36s steps(3, end) infinite,
    character-squish 0.22s ease-out forwards;
}
@keyframes character-squish {
  0%   { transform: scaleY(1)    scaleX(1); }
  35%  { transform: scaleY(0.86) scaleX(1.10); }
  100% { transform: scaleY(1)    scaleX(1); }
}

/* When jumping the shadow shrinks (further from ground) */
.character-canvas.jump ~ .character-shadow,
.character-stage.jumping .character-shadow {
  animation: shadow-jump 0.85s cubic-bezier(0.25, 0.6, 0.3, 1);
}
@keyframes shadow-jump {
  0%, 100% { transform: scaleX(1.0); opacity: 0.85; }
  50%      { transform: scaleX(0.3); opacity: 0.25; }
}

/* ── Foreground ──────────────────────────────────────────────────────── */

.layer-foreground {
  bottom: 0; top: auto; height: 30%;
  z-index: 6;
}
.fg-tile {
  flex: 0 0 50%;
  position: relative;
  height: 100%;
}
.foreground-bush {
  position: absolute;
  bottom: -10px;
  left: -40px;
  width: 280px;
  height: 110px;
  background: radial-gradient(ellipse at center top,
    var(--c-jungle-light) 0%,
    var(--c-jungle-mid)   50%,
    transparent 75%);
  filter: brightness(0.75);
}

/* ── Fireflies ───────────────────────────────────────────────────────── */

.fireflies {
  position: absolute; inset: 0; pointer-events: none;
  z-index: 7;
  opacity: 0;
  transition: opacity 1.5s ease;
}
html[data-time="dusk"] .fireflies,
html[data-time="night"] .fireflies { opacity: 1; }

/* ── UI ──────────────────────────────────────────────────────────────── */

.ui-top {
  position: absolute;
  top: 24px; left: 50%;
  transform: translateX(-50%);
  z-index: 9;
  text-align: center;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.game-title {
  display: flex; flex-direction: column;
  align-items: center; gap: 4px;
}

/* ── Persistent how-to-play controls bar ─────────────────────────────── */
.controls-bar {
  display: flex;
  gap: 14px;
  padding: 8px 16px;
  background: rgba(10, 22, 16, 0.6);
  border: 1px solid var(--c-gold-deep);
  border-radius: 22px;
  backdrop-filter: blur(4px);
  pointer-events: none;
  user-select: none;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}
.controls-bar-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  font-family: 'Press Start 2P', monospace;
  min-width: 56px;
}
.controls-bar-action {
  font-size: 7px;
  letter-spacing: 0.18em;
  color: var(--c-bone);
  opacity: 0.6;
  text-transform: uppercase;
}
.controls-bar-key {
  font-size: 9px;
  letter-spacing: 0.05em;
  color: var(--c-gold);
}
.controls-bar-item--hl .controls-bar-action {
  color: var(--c-gold);
  opacity: 1;
}
.controls-bar-item--hl .controls-bar-key {
  color: var(--c-bone);
  background: rgba(212, 160, 86, 0.18);
  padding: 1px 5px;
  border-radius: 2px;
}

@media (max-width: 540px) {
  .controls-bar {
    flex-wrap: wrap;
    gap: 6px 10px;
    padding: 6px 10px;
    max-width: 95vw;
    justify-content: center;
  }
  .controls-bar-item { min-width: 48px; }
  .controls-bar-action { font-size: 6px; }
  .controls-bar-key { font-size: 8px; }
}

/* ── Predator-clear triumph flash on Tygra ───────────────────────────── */
.character-canvas.triumph {
  filter: drop-shadow(0 4px 0 rgba(0,0,0,0.4))
          drop-shadow(0 0 24px rgba(255, 215, 120, 0.9));
  animation:
    tygra-run 0.36s steps(3, end) infinite,
    triumph-pulse 0.7s ease-out forwards;
}
@keyframes triumph-pulse {
  0%   { filter: drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
  20%  { filter: drop-shadow(0 4px 0 rgba(0,0,0,0.4))
                drop-shadow(0 0 32px rgba(255, 235, 160, 1)); }
  100% { filter: drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
}
.game-title-line1 {
  font-family: 'Press Start 2P', monospace;
  font-size: 22px;
  letter-spacing: 0.18em;
  color: var(--c-gold);
  text-shadow: 0 2px 0 #000, 0 0 18px rgba(212, 160, 86, 0.4);
}
.game-title-line2 {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-size: 13px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--c-bone);
  opacity: 0.75;
  text-shadow: 0 1px 4px rgba(0,0,0,0.8);
}

.ui-bottom {
  position: absolute;
  bottom: 20px; left: 0; right: 0;
  z-index: 9;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  pointer-events: none;
}
.ui-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
  pointer-events: auto;
}

.ui-distance,
.ui-coins {
  font-family: 'Press Start 2P', monospace;
  font-size: 16px;
  letter-spacing: 0.12em;
  color: var(--c-bone);
  background: rgba(10, 22, 16, 0.7);
  border: 1px solid var(--c-gold-deep);
  padding: 10px 14px;
  border-radius: 4px;
  display: flex; align-items: center; gap: 8px;
  backdrop-filter: blur(4px);
}
.ui-distance-num  { color: var(--c-gold); }
.ui-distance-unit { font-size: 11px; opacity: 0.7; }

.ui-coins {
  font-size: 13px;
  padding: 8px 12px;
}
.ui-coins-icon { color: var(--c-gold); font-size: 14px; }
.ui-coins-num  { color: var(--c-bone); }

.ui-controls,
.ui-direction { display: flex; gap: 8px; pointer-events: auto; }

.ui-btn {
  background: rgba(10, 22, 16, 0.7);
  border: 1px solid var(--c-gold-deep);
  color: var(--c-bone);
  width: 44px; height: 44px;
  border-radius: 4px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 18px;
  transition: background 0.2s ease, border-color 0.2s ease,
              transform 0.15s ease, color 0.2s ease;
  backdrop-filter: blur(4px);
}
.ui-btn:hover, .ui-btn:focus-visible {
  background: rgba(74, 66, 57, 0.85);
  border-color: var(--c-gold);
  transform: scale(1.05);
  outline: none;
}

/* Active direction button — filled gold so the selected facing is
   unmistakable. Pulses subtly to indicate "this is the live one". */
.ui-btn.active {
  background: var(--c-gold);
  border-color: var(--c-bone);
  color: var(--c-jungle-deep);
  box-shadow: 0 0 12px rgba(212, 160, 86, 0.55);
}
.ui-btn.active:hover, .ui-btn.active:focus-visible {
  background: var(--c-bone);
  border-color: var(--c-gold);
}

/* Direction buttons are slightly smaller to feel like a paired unit */
.ui-btn--dir {
  font-size: 14px;
}

/* ── Live "defeated" counter — right side of screen during play ─────── */

.kill-counter {
  position: absolute;
  top: 24px;
  right: 16px;
  z-index: 9;
  background: rgba(10, 22, 16, 0.65);
  border: 1px solid var(--c-gold-deep);
  border-radius: 6px;
  padding: 10px 12px;
  backdrop-filter: blur(4px);
  pointer-events: none;
  user-select: none;
  min-width: 124px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
.kill-counter-title {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  letter-spacing: 0.2em;
  color: var(--c-gold);
  text-transform: uppercase;
  margin-bottom: 8px;
  text-align: center;
  border-bottom: 1px solid rgba(212, 160, 86, 0.25);
  padding-bottom: 6px;
}
.kill-counter-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.kill-counter-row {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-family: 'Press Start 2P', monospace;
  transition: color 0.3s ease;
}
.kill-counter-sample {
  /* Tighten the .tips-sample defaults to a smaller chip for the counter */
  width: 24px !important;
  height: 18px !important;
  border-radius: 2px !important;
}
.kill-counter-name {
  font-size: 8px;
  letter-spacing: 0.1em;
  color: var(--c-bone);
  opacity: 0.75;
  text-transform: uppercase;
}
.kill-counter-num {
  font-size: 11px;
  color: var(--c-gold);
  text-align: right;
  min-width: 18px;
}
.kill-counter-row--boss .kill-counter-name { color: var(--c-crimson); opacity: 1; }
.kill-counter-row--boss .kill-counter-num  { color: var(--c-crimson); }

/* Brief pulse when a count increments */
.kill-counter-num.pulse {
  animation: kill-num-pulse 0.45s ease-out;
}
@keyframes kill-num-pulse {
  0%   { transform: scale(1);   color: var(--c-bone); }
  35%  { transform: scale(1.4); color: var(--c-bone); }
  100% { transform: scale(1);   color: var(--c-gold); }
}

@media (max-width: 720px) {
  .kill-counter { min-width: 100px; padding: 8px 10px; right: 8px; top: 14px; }
  .kill-counter-sample { width: 18px !important; height: 14px !important; }
  .kill-counter-name { font-size: 7px; }
  .kill-counter-num  { font-size: 9px; }
}
@media (max-width: 480px) {
  /* On phones we hide the in-game counter (controls + distance + coins
     already crowd the screen) — the game-over modal still shows it. */
  .kill-counter { display: none; }
}

/* ── Game-over "defeated this run" breakdown ─────────────────────────── */

.game-over-defeated {
  margin-bottom: 18px;
  padding: 12px;
  background: rgba(10, 22, 16, 0.5);
  border: 1px solid rgba(212, 160, 86, 0.3);
  border-radius: 4px;
}
.game-over-defeated-title {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  letter-spacing: 0.22em;
  color: var(--c-gold);
  text-transform: uppercase;
  margin-bottom: 10px;
  text-align: center;
}
.game-over-defeated-list {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.game-over-defeated-row {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 5px 8px;
  background: rgba(10, 22, 16, 0.4);
  border-radius: 3px;
  font-family: 'Press Start 2P', monospace;
}
.game-over-defeated-row--boss {
  grid-column: span 2;
  border: 1px solid var(--c-crimson);
  background: rgba(60, 16, 16, 0.4);
}
.game-over-defeated-name {
  font-size: 8px;
  letter-spacing: 0.12em;
  color: var(--c-bone);
  text-transform: uppercase;
}
.game-over-defeated-num {
  font-size: 11px;
  color: var(--c-gold);
}
.game-over-defeated-row--boss .game-over-defeated-name { color: var(--c-crimson); }
.game-over-defeated-row--boss .game-over-defeated-num  { color: var(--c-crimson); }

@media (max-width: 540px) {
  .game-over-defeated-list { grid-template-columns: 1fr; }
  .game-over-defeated-row--boss { grid-column: span 1; }
}

/* ── Hint ────────────────────────────────────────────────────────────── */

.hint {
  position: absolute;
  top: 35%; left: 50%;
  transform: translateX(-50%);
  z-index: 8;
  text-align: center;
  pointer-events: none;
  animation: hint-pulse 2s ease-in-out infinite;
  transition: opacity 0.5s ease;
}
.hint.hidden { opacity: 0; }
.hint-text {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 14px;
  letter-spacing: 0.15em;
  color: var(--c-gold);
  text-shadow: 0 2px 0 #000, 0 0 12px rgba(212, 160, 86, 0.6);
  margin-bottom: 6px;
}
.hint-sub {
  display: block;
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-size: 13px;
  color: var(--c-bone);
  opacity: 0.85;
  text-shadow: 0 1px 4px rgba(0,0,0,0.8);
}
.hint-sub--arrows {
  margin-top: 8px;
  font-family: 'Press Start 2P', monospace;
  font-size: 10px;
  font-style: normal;
  letter-spacing: 0.12em;
  color: var(--c-gold);
  opacity: 0.75;
}
@keyframes hint-pulse {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1.0; }
}

/* ── Vignette ────────────────────────────────────────────────────────── */

.vignette {
  position: absolute; inset: 0;
  z-index: 10;
  pointer-events: none;
  background:
    radial-gradient(ellipse at center,
      transparent 30%,
      rgba(0,0,0, calc(var(--vignette-deep) * 0.4)) 70%,
      rgba(0,0,0, var(--vignette-deep)) 100%),
    var(--ambient-tint);
  mix-blend-mode: multiply;
}

/* ── Tips / how-to-play overlay ──────────────────────────────────────── */

.tips-overlay {
  position: fixed;
  inset: 0;
  z-index: 110;
  background: rgba(10, 22, 16, 0.88);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: modal-fade 0.4s ease;
  overflow-y: auto;
}
.tips-overlay[hidden] { display: none; }

.tips-card {
  position: relative;
  width: 100%;
  max-width: 560px;
  background:
    linear-gradient(135deg,
      rgba(74, 66, 57, 0.97) 0%,
      rgba(26, 58, 37, 0.97) 100%);
  border: 1px solid var(--c-gold);
  border-radius: 6px;
  padding: 30px 28px 22px;
  box-shadow:
    0 0 0 1px rgba(212, 160, 86, 0.25),
    0 20px 60px rgba(0,0,0,0.6);
  animation: card-rise 0.45s ease;
  max-height: 90vh;
  /* Flex column so the footer (START button + hint) stays pinned at the
     bottom while only the content above scrolls. Player never has to
     scroll just to find the START button. */
  display: flex;
  flex-direction: column;
}
.tips-card-scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  /* Reserve space so scrollbar doesn't cover content */
  padding-right: 4px;
  margin-right: -4px;
  /* Subtle fade hint that content might be scrolled */
  mask-image: linear-gradient(to bottom, black 0%, black calc(100% - 16px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black calc(100% - 16px), transparent 100%);
}
.tips-card-footer {
  flex: 0 0 auto;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(212, 160, 86, 0.25);
}

.tips-close {
  position: absolute;
  top: 10px; right: 12px;
  width: 32px; height: 32px;
  background: transparent;
  border: none;
  color: var(--c-bone);
  font-size: 24px;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 0.2s ease, background 0.2s ease;
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
}
.tips-close:hover, .tips-close:focus-visible {
  opacity: 1;
  background: rgba(255,255,255,0.08);
  outline: none;
}

.tips-eyebrow {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
  letter-spacing: 0.3em;
  color: var(--c-gold);
  text-transform: uppercase;
  margin-bottom: 8px;
}

.tips-title {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 400;
  font-style: italic;
  font-size: 26px;
  color: var(--c-bone);
  margin-bottom: 16px;
  line-height: 1.1;
}

.tips-intro {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 14px;
  line-height: 1.5;
  color: var(--c-bone);
  opacity: 0.85;
  margin-bottom: 20px;
  font-style: italic;
}
.tips-intro strong {
  color: var(--c-gold);
  font-weight: 600;
  font-style: normal;
}

/* Device-compatibility notice — small chip near top of the start screen. */
.tips-device-notice {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 12px 14px;
  margin: 18px 0;
  background: rgba(212, 160, 86, 0.10);
  border: 1px solid var(--c-gold-deep);
  border-left: 3px solid var(--c-gold);
  border-radius: 4px;
}
.tips-device-icon {
  font-family: 'Press Start 2P', monospace;
  font-size: 22px;
  color: var(--c-gold);
  line-height: 1;
  margin-top: 2px;
  flex-shrink: 0;
}
.tips-device-title {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
  letter-spacing: 0.15em;
  color: var(--c-gold);
  text-transform: uppercase;
  margin-bottom: 6px;
  line-height: 1.4;
}
.tips-device-body {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 12px;
  line-height: 1.5;
  color: var(--c-bone);
  opacity: 0.85;
  font-style: italic;
}

/* Hint text below the START button reinforces input options. */
.tips-start-hint {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  letter-spacing: 0.2em;
  color: var(--c-bone);
  opacity: 0.55;
  text-transform: uppercase;
  text-align: center;
  margin-top: 10px;
}

/* Last-resort "wipe cache + reload" button. Subtle by default so it
   doesn't distract from START, but accessible if a player ever needs
   to recover from a stuck cache. */
.tips-clear {
  display: block;
  margin: 16px auto 0;
  background: transparent;
  border: 1px solid rgba(212, 160, 86, 0.35);
  color: var(--c-bone);
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 8px 14px;
  border-radius: 3px;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.tips-clear strong {
  color: var(--c-gold);
  font-weight: 600;
  font-style: normal;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 10px;
}
.tips-clear:hover, .tips-clear:focus-visible {
  opacity: 1;
  border-color: var(--c-gold);
  outline: none;
}

/* "New version ready" banner that appears top-center when the SW
   detects a new build is installed and ready to take over. */
.update-banner {
  position: fixed;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
  letter-spacing: 0.18em;
  color: var(--c-jungle-deep);
  background: var(--c-gold);
  border: 1px solid var(--c-bone);
  border-radius: 4px;
  padding: 10px 16px;
  cursor: pointer;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
  text-transform: uppercase;
  animation: update-banner-pop 0.5s ease-out;
}
.update-banner span {
  color: var(--c-crimson);
  font-weight: 700;
  margin-right: 6px;
}
.update-banner:hover { background: var(--c-bone); }
@keyframes update-banner-pop {
  0%   { opacity: 0; transform: translate(-50%, -16px); }
  100% { opacity: 1; transform: translate(-50%, 0); }
}

@media (max-width: 540px) {
  .tips-device-notice { padding: 10px; gap: 10px; }
  .tips-device-icon   { font-size: 18px; }
  .tips-device-title  { font-size: 8px; }
  .tips-device-body   { font-size: 11px; }
}

.tips-section {
  margin-bottom: 18px;
  padding-top: 14px;
  border-top: 1px solid rgba(212, 160, 86, 0.25);
}

.tips-section-title {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
  letter-spacing: 0.25em;
  color: var(--c-gold);
  text-transform: uppercase;
  margin-bottom: 12px;
}

.tips-grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
.tips-grid li {
  display: grid;
  grid-template-columns: 56px 1fr;
  grid-template-rows: auto auto;
  gap: 0 12px;
  align-items: center;
  padding: 8px;
  background: rgba(10, 22, 16, 0.45);
  border: 1px solid rgba(212, 160, 86, 0.25);
  border-radius: 4px;
}
.tips-grid li.tips-grid-boss {
  grid-column: span 2;
  border-color: var(--c-crimson);
  background: rgba(60, 16, 16, 0.45);
}
.tips-name {
  font-family: 'Press Start 2P', monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--c-bone);
  text-transform: uppercase;
}
.tips-hint {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 12px;
  font-style: italic;
  color: var(--c-bone);
  opacity: 0.75;
}
.tips-grid li.tips-grid-boss .tips-hint {
  color: var(--c-crimson);
  opacity: 1;
  font-weight: 600;
}

/* Mini sample blocks — small inline renderings of each obstacle */
.tips-sample {
  grid-row: span 2;
  width: 52px; height: 40px;
  display: block;
  position: relative;
  background: var(--c-jungle-deep);
  border: 1px solid rgba(212, 160, 86, 0.2);
  border-radius: 3px;
  overflow: hidden;
}
.tips-sample::before {
  content: '';
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}
.tips-sample-log::before {
  bottom: 6px;
  width: 32px; height: 12px;
  background: linear-gradient(to bottom, #6b4a2a, #2e1d0e);
  border-top: 1px solid #8b6a3e;
  border-radius: 2px;
}
.tips-sample-rock::before {
  bottom: 6px;
  width: 26px; height: 20px;
  background: linear-gradient(155deg, #8a8580, #5a5552 50%, #2e2a28);
  border-radius: 50% 50% 30% 30% / 60% 60% 35% 35%;
  border-top: 1px solid #aaa5a0;
}
.tips-sample-thorns::before {
  bottom: 6px;
  width: 44px; height: 8px;
  background: linear-gradient(to bottom, #2d5f3e, #1a3a25);
  border-radius: 2px;
}
.tips-sample-thorns::after {
  content: '';
  position: absolute;
  bottom: 14px; left: 50%;
  width: 44px; height: 7px;
  background: var(--c-crimson);
  clip-path: polygon(
    0 100%, 10% 0, 20% 100%, 30% 0, 40% 100%, 50% 0,
    60% 100%, 70% 0, 80% 100%, 90% 0, 100% 100%
  );
  transform: translateX(-50%);
}
.tips-sample-snake::before {
  bottom: 8px;
  width: 36px; height: 8px;
  background: linear-gradient(to bottom, #4a8a4a, #1a3a25);
  border-radius: 50% 30% 30% 50%;
  border-top: 1px solid #6abb6a;
}
.tips-sample-snake::after {
  content: '';
  position: absolute;
  bottom: 11px; right: 11px;
  width: 2px; height: 2px;
  background: #ffcc33;
  border-radius: 50%;
}
.tips-sample-predator::before {
  bottom: 0;
  width: 40px; height: 40px;
  background: url('assets/images/shadow-predator.png') no-repeat center bottom;
  background-size: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 0 4px rgba(220, 30, 30, 0.6));
}

.tips-controls {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tips-controls li {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 13px;
  color: var(--c-bone);
  opacity: 0.9;
  display: flex;
  align-items: center;
  gap: 4px;
}
.tips-controls kbd {
  display: inline-block;
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
  letter-spacing: 0.05em;
  background: rgba(212, 160, 86, 0.18);
  border: 1px solid var(--c-gold-deep);
  color: var(--c-gold);
  padding: 3px 6px;
  border-radius: 2px;
  margin: 0 2px;
}
.tips-coin {
  color: var(--c-gold);
  font-size: 16px;
}
.tips-controls strong {
  color: var(--c-gold);
  font-weight: 600;
}

.tips-start {
  font-family: 'Press Start 2P', monospace;
  font-size: 12px;
  letter-spacing: 0.22em;
  color: var(--c-jungle-deep);
  background: var(--c-gold);
  border: none;
  padding: 16px 28px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.15s ease;
  text-transform: uppercase;
  width: 100%;
  margin-top: 6px;
}
.tips-start:hover, .tips-start:focus-visible {
  background: var(--c-bone);
  transform: translateY(-2px);
  outline: none;
}

@media (max-width: 540px) {
  .tips-title    { font-size: 22px; }
  .tips-intro    { font-size: 13px; }
  .tips-grid     { grid-template-columns: 1fr; }
  .tips-grid li.tips-grid-boss { grid-column: span 1; }
  .tips-sample   { width: 44px; height: 34px; }
}

/* ── Pause overlay ───────────────────────────────────────────────────── */

.pause-overlay {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(10, 22, 16, 0.55);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Don't capture clicks — let them fall through to .scene so a tap
     anywhere resumes the game. The pause button stays clickable because
     it lives outside this overlay. */
  pointer-events: none;
  animation: modal-fade 0.2s ease;
}
.pause-overlay[hidden] { display: none; }

.pause-card {
  text-align: center;
  pointer-events: none;
  user-select: none;
}

.pause-title {
  font-family: 'Press Start 2P', monospace;
  font-size: 32px;
  letter-spacing: 0.22em;
  color: var(--c-gold);
  text-shadow:
    0 4px 0 #000,
    0 0 24px rgba(212, 160, 86, 0.45);
  margin-bottom: 14px;
}

.pause-hint {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-size: 14px;
  color: var(--c-bone);
  opacity: 0.8;
  letter-spacing: 0.05em;
  text-shadow: 0 1px 4px rgba(0,0,0,0.8);
  margin-bottom: 18px;
}

/* How-to-play button on the pause overlay. Pointer-events override
   is required because the parent .pause-overlay has pointer-events:none
   (so taps anywhere on the backdrop resume the game). */
.pause-help-btn {
  pointer-events: auto;
  font-family: 'Press Start 2P', monospace;
  font-size: 10px;
  letter-spacing: 0.2em;
  color: var(--c-jungle-deep);
  background: var(--c-gold);
  border: 1px solid var(--c-bone);
  padding: 12px 22px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.15s ease, border-color 0.2s ease;
  text-transform: uppercase;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
}
.pause-help-btn:hover, .pause-help-btn:focus-visible {
  background: var(--c-bone);
  border-color: var(--c-gold);
  transform: translateY(-2px);
  outline: none;
}

@media (max-width: 480px) {
  .pause-title { font-size: 22px; letter-spacing: 0.18em; }
  .pause-hint  { font-size: 12px; }
}

/* When paused, freeze every gameplay-related CSS animation under .scene.
   Parallax + obstacles + particles are JS-controlled and frozen by their
   own update gates. Atmospheric stuff (stars, fireflies, sky cycle) keeps
   going on purpose — feels alive, not crashed. */
.scene.paused .character-canvas,
.scene.paused .character-flip,
.scene.paused .character-shadow,
.scene.paused .character-glow,
.scene.paused .vine {
  animation-play-state: paused;
}

/* ── Hit-stop — the classic action-game pause-on-impact technique.
   When `.hit-stopped` is applied to <body>, every CSS animation on the
   page freezes for ~70ms. JS updates (parallax, physics) are gated on
   gameOver/hitStop separately. Combined: total freeze + impact emphasis. */
body.hit-stopped *,
body.hit-stopped *::before,
body.hit-stopped *::after {
  animation-play-state: paused !important;
  transition: none !important;
}

/* ── Close-call gold flash — when an obstacle passes within ~25px of
   Tygra's hit-radius without collision. Briefly halo's her in gold. */
.character-canvas.close-call {
  animation:
    tygra-run 0.36s steps(3, end) infinite,
    close-call-flash 0.42s ease-out forwards;
}
@keyframes close-call-flash {
  0%   { filter: drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
  25%  { filter: drop-shadow(0 4px 0 rgba(0,0,0,0.4))
                drop-shadow(0 0 28px rgba(255, 235, 160, 0.95))
                drop-shadow(0 0 8px  rgba(255, 215, 100, 0.7)); }
  100% { filter: drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
}

/* ── Milestone banner — pops in big when distance crosses a named
   threshold. Larger and longer-lived than the combo flash. */
.milestone-banner {
  position: absolute;
  top: 32%;
  left: 50%;
  z-index: 35;
  transform: translate(-50%, -50%);
  pointer-events: none;
  text-align: center;
  text-shadow:
    0 4px 0 #000,
    0 0 32px rgba(212, 160, 86, 0.85);
  animation: milestone-pop 1.5s ease-out;
}
.milestone-banner[hidden] { display: none; }
.milestone-banner-num {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 56px;
  color: var(--c-gold);
  margin-bottom: 10px;
  letter-spacing: 0.05em;
}
.milestone-banner-num .unit {
  font-size: 26px;
  opacity: 0.7;
  margin-left: 4px;
}
.milestone-banner-name {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 14px;
  letter-spacing: 0.35em;
  color: var(--c-bone);
}
@keyframes milestone-pop {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.6); }
  15%  { opacity: 1; transform: translate(-50%, -50%) scale(1.18); }
  30%  {              transform: translate(-50%, -50%) scale(1.0); }
  70%  { opacity: 1; transform: translate(-50%, -50%) scale(1.0); }
  100% { opacity: 0; transform: translate(-50%, -65%) scale(1.05); }
}

@media (max-width: 540px) {
  .milestone-banner-num  { font-size: 38px; }
  .milestone-banner-num .unit { font-size: 18px; }
  .milestone-banner-name { font-size: 11px; letter-spacing: 0.28em; }
}

/* ── Distance counter pulse — quick beat when the integer value
   increments. Subtler than the milestone banner; happens continuously. */
.ui-distance-num.pulse {
  animation: distance-pulse 0.18s ease-out;
}
@keyframes distance-pulse {
  0%   { transform: scale(1);    text-shadow: none; }
  45%  { transform: scale(1.12); text-shadow: 0 0 12px rgba(212, 160, 86, 0.8); }
  100% { transform: scale(1);    text-shadow: none; }
}

/* ── Death animation — Tygra rotates over and dims ──────────────────── */

.character-canvas.dead {
  animation: tygra-fall 0.95s cubic-bezier(0.4, 0.0, 0.9, 0.5) forwards;
}
/* Choreographed: impact-flash → knockback → tumble → settle.
   Each phase has its own pose so the death reads as a real moment
   rather than a single rotation. */
@keyframes tygra-fall {
  0%   { transform: translateX(0)    translateY(0)    rotate(0deg)   scaleX(1);
         filter: brightness(1)  drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
  /* Impact flash — frame of brightness, slight squish, recoil */
  8%   { transform: translateX(14px) translateY(-6px) rotate(-4deg)  scaleX(0.94);
         filter: brightness(1.6) drop-shadow(0 4px 0 rgba(0,0,0,0.4))
                 drop-shadow(0 0 20px rgba(255, 80, 80, 0.6)); }
  /* Knockback skid */
  22%  { transform: translateX(12px) translateY(-2px) rotate(-18deg) scaleX(0.98);
         filter: brightness(1.1) drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
  /* Mid-tumble */
  50%  { transform: translateX(8px)  translateY(-12px) rotate(-55deg) scaleX(1);
         filter: brightness(0.8) drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
  /* Almost landed */
  75%  { transform: translateX(4px)  translateY(14px)  rotate(-88deg) scaleX(1.02);
         filter: brightness(0.55) drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
  /* Settled — dim, slight saturate-out so she fades into the scene */
  100% { transform: translateX(0)    translateY(24px)  rotate(-92deg) scaleX(1);
         filter: brightness(0.4) saturate(0.4) drop-shadow(0 4px 0 rgba(0,0,0,0.4)); }
}

/* ── Game over modal ─────────────────────────────────────────────────── */

.game-over {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(10, 22, 16, 0.86);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: modal-fade 0.4s ease;
}
.game-over[hidden] { display: none; }

.game-over-card {
  width: 100%;
  max-width: 420px;
  background:
    linear-gradient(135deg,
      rgba(74, 66, 57, 0.95) 0%,
      rgba(26, 58, 37, 0.95) 100%);
  border: 1px solid var(--c-gold);
  border-radius: 6px;
  padding: 32px 28px 26px;
  text-align: center;
  box-shadow:
    0 0 0 1px rgba(212, 160, 86, 0.25),
    0 20px 60px rgba(0,0,0,0.6);
  animation: card-rise 0.45s ease;
}

.game-over-eyebrow {
  font-family: 'Press Start 2P', monospace;
  font-size: 9px;
  letter-spacing: 0.3em;
  color: var(--c-crimson);
  text-transform: uppercase;
  margin-bottom: 14px;
}

.game-over-title {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 400;
  font-style: italic;
  font-size: 36px;
  line-height: 1.1;
  color: var(--c-bone);
  margin-bottom: 22px;
  letter-spacing: -0.01em;
}

/* "Caused by" — shows the obstacle that killed Tygra. Lets the player
   verify visually that the collision was fair. */
.game-over-cause {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-bottom: 20px;
  padding: 14px;
  background: rgba(10, 22, 16, 0.5);
  border: 1px solid rgba(212, 160, 86, 0.3);
  border-radius: 4px;
}
.game-over-cause-label {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  letter-spacing: 0.2em;
  color: var(--c-bone);
  opacity: 0.6;
  text-transform: uppercase;
}
.game-over-cause-display {
  display: flex;
  align-items: center;
  gap: 14px;
}
.game-over-cause-sample {
  width: 60px;
  height: 44px;
  display: block;
  position: relative;
  background: var(--c-jungle-deep);
  border: 1px solid rgba(212, 160, 86, 0.2);
  border-radius: 3px;
  overflow: hidden;
}
.game-over-cause-sample::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 4px;
  transform: translateX(-50%);
}
.game-over-cause-sample[data-type="log"]::before {
  width: 38px; height: 14px;
  background: linear-gradient(to bottom, #6b4a2a, #2e1d0e);
  border-top: 1px solid #8b6a3e;
  border-radius: 2px;
}
.game-over-cause-sample[data-type="rock"]::before {
  width: 30px; height: 26px;
  background: linear-gradient(155deg, #8a8580, #5a5552, #2e2a28);
  border-radius: 50% 50% 30% 30% / 60% 60% 35% 35%;
  border-top: 1px solid #aaa5a0;
}
.game-over-cause-sample[data-type="thorns"]::before {
  width: 50px; height: 8px;
  background: linear-gradient(to bottom, #2d5f3e, #1a3a25);
  border-radius: 2px;
}
.game-over-cause-sample[data-type="thorns"]::after {
  content: '';
  position: absolute;
  bottom: 12px; left: 50%;
  width: 50px; height: 8px;
  background: var(--c-crimson);
  clip-path: polygon(
    0 100%, 10% 0, 20% 100%, 30% 0, 40% 100%, 50% 0,
    60% 100%, 70% 0, 80% 100%, 90% 0, 100% 100%
  );
  transform: translateX(-50%);
}
.game-over-cause-sample[data-type="snake"]::before {
  width: 40px; height: 10px;
  background: linear-gradient(to bottom, #4a8a4a, #1a3a25);
  border-radius: 50% 30% 30% 50%;
  border-top: 1px solid #6abb6a;
}
.game-over-cause-sample[data-type="snake"]::after {
  content: '';
  position: absolute;
  bottom: 12px; right: 14px;
  width: 3px; height: 3px;
  background: #ffcc33;
  border-radius: 50%;
}
.game-over-cause-sample[data-type="predator"]::before {
  /* Use the actual sprite for the predator */
  width: 56px; height: 40px;
  background: url('assets/images/shadow-predator.png') no-repeat center bottom;
  background-size: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 0 4px rgba(220, 30, 30, 0.6));
}
.game-over-cause-name {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px;
  letter-spacing: 0.15em;
  color: var(--c-gold);
  text-transform: uppercase;
}
.game-over-cause[data-type="predator"] .game-over-cause-name {
  color: var(--c-crimson);
  text-shadow: 0 0 6px rgba(255, 30, 30, 0.6);
}

.game-over-scores {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 22px;
}
.game-over-score {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px 8px;
  background: rgba(10, 22, 16, 0.5);
  border-radius: 4px;
  border: 1px solid rgba(212, 160, 86, 0.3);
}
.game-over-score-label {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  letter-spacing: 0.18em;
  color: var(--c-bone);
  opacity: 0.6;
  text-transform: uppercase;
}
.game-over-score-num {
  font-family: 'Press Start 2P', monospace;
  font-size: 19px;
  color: var(--c-gold);
}
.game-over-score-num .unit {
  font-size: 11px;
  opacity: 0.65;
  margin-left: 3px;
}

.game-over-restart {
  font-family: 'Press Start 2P', monospace;
  font-size: 12px;
  letter-spacing: 0.22em;
  color: var(--c-jungle-deep);
  background: var(--c-gold);
  border: none;
  padding: 16px 28px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.15s ease;
  text-transform: uppercase;
  width: 100%;
  margin-bottom: 14px;
}
.game-over-restart:hover, .game-over-restart:focus-visible {
  background: var(--c-bone);
  transform: translateY(-2px);
  outline: none;
}
.game-over-hint {
  font-family: 'Press Start 2P', monospace;
  font-size: 8px;
  letter-spacing: 0.2em;
  color: var(--c-bone);
  opacity: 0.55;
  text-transform: uppercase;
}

@media (max-width: 480px) {
  .game-over-title { font-size: 28px; }
  .game-over-score-num { font-size: 16px; }
  .game-over-restart { font-size: 11px; padding: 14px 20px; }
}

/* ── Landing copy (below the fold) ───────────────────────────────────── */

.landing-copy {
  position: relative;
  z-index: 1;
  max-width: 640px;
  margin: 0 auto;
  padding: 80px 24px 60px;
  text-align: center;
  background: var(--c-jungle-deep);
}
.landing-eyebrow {
  font-family: 'Press Start 2P', monospace;
  font-size: 10px;
  letter-spacing: 0.3em;
  color: var(--c-gold);
  text-transform: uppercase;
  margin-bottom: 18px;
}
.landing-title {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 400;
  font-size: clamp(2.2rem, 5vw, 3.5rem);
  letter-spacing: -0.02em;
  color: var(--c-bone);
  margin-bottom: 20px;
}
.landing-body {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-size: 1.2rem;
  line-height: 1.6;
  color: var(--c-bone);
  opacity: 0.85;
  margin-bottom: 32px;
}
.landing-cta {
  display: inline-block;
  font-family: 'Press Start 2P', monospace;
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--c-jungle-deep);
  background: var(--c-gold);
  padding: 16px 28px;
  border-radius: 4px;
  text-decoration: none;
  transition: background 0.2s ease, transform 0.15s ease;
  text-transform: uppercase;
}
.landing-cta:hover {
  background: var(--c-bone);
  transform: translateY(-2px);
}

/* ── Responsive ─────────────────────────────────────────────────────── */

@media (max-width: 720px) {
  .character-canvas    { --frame-w: min(20vh, 190px); }
  .character-glow      { width: 150px; height: 150px; }
  .character-shadow    { width: 56px; height: 10px; }
  .character-particles { width: 320px; height: 320px; }
  .game-title-line1  { font-size: 18px; }
  .game-title-line2  { font-size: 11px; }
  .ui-distance       { font-size: 13px; padding: 8px 10px; }
  .ui-distance-unit  { font-size: 9px; }
  .ui-btn            { width: 40px; height: 40px; font-size: 16px; }
  .hint-text         { font-size: 11px; }
  .hint-sub          { font-size: 12px; }
  .obstacle          { width: 42px; height: 20px; }
  .foreground-bush   { width: 220px; height: 90px; }
}
@media (max-width: 480px) {
  .ui-top    { top: 12px; }
  .ui-bottom { bottom: 12px; padding: 0 12px; }
  .character-canvas    { --frame-w: min(18vh, 160px); }
  .character-glow      { width: 130px; height: 130px; }
  .character-shadow    { width: 50px; height: 9px; }
  .character-particles { width: 260px; height: 280px; }
  .character-stage     { bottom: 16%; }
  .obstacle            { width: 36px; height: 18px; }
  @keyframes tygra-jump {
    0%   { transform: translateY(0)    rotate(-2deg); }
    20%  { transform: translateY(-65px) rotate(-4deg); }
    50%  { transform: translateY(-90px) rotate(0deg); }
    80%  { transform: translateY(-65px) rotate(4deg); }
    100% { transform: translateY(0)    rotate(0deg); }
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
