/* ============================================
   SCENE KIT -- shared rules for the layered parallax scenes
   Used by game/js/scene-kit.js (ParallaxStage + SceneKit) and every level
   scene built on it (forest-scene.css for Level 1, cave-scene.css for
   Level 2). Level files add their own palette, covers and characters.

   Coordinate system: a 960x540 "stage" scaled to the viewport with a
   single CSS transform, so every prop is placed in fixed design pixels.
   Layers are full-height strips translated by camX x parallax.
   ============================================ */

.fs-root {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #000;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* Hosts that reset img { max-width: 100% } (the Claude artifact viewer does)
   would collapse every prop image, because props live in zero-width anchor
   boxes. Sizes here are explicit, so opt the whole scene out of that reset. */
.fs-root img {
  max-width: none;
  max-height: none;
}

.fs-stage {
  position: absolute;
  top: 0; left: 0;
  width: 960px;
  height: 540px;
  transform-origin: 0 0;
  will-change: transform;
}

.fs-layer {
  position: absolute;
  top: 0; left: 0;
  height: 540px;
  will-change: transform;
  pointer-events: none;
}
.fs-layer.fs-layer-mid { pointer-events: auto; }

/* ---- Backdrop (mirror-tiled pair so the seam is invisible) ---- */
.fs-backdrop img {
  position: absolute;
  top: 0;
  height: 540px;
  width: auto;
  image-rendering: auto;
}
.fs-backdrop img.flip { transform: scaleX(-1); }

/* ---- Ground tiles ---- */
.fs-ground img {
  position: absolute;
  bottom: 0;
  height: 240px;
  width: auto;
  image-rendering: auto;
}
.fs-ground img.flip { transform: scaleX(-1); }

/* ---- Props ----
   .fs-prop sits at (x, y) = bottom-centre anchor in layer space.
   .fs-anchor does the anchoring so .fs-body is free for animations. */
.fs-prop {
  position: absolute;
  width: 0;
  height: 0;
}
.fs-anchor {
  position: absolute;
  left: 0;
  bottom: 0;
  transform: translateX(-50%);
  display: flex;
  align-items: flex-end;
}
.fs-prop.top-anchored .fs-anchor {
  top: 0;
  bottom: auto;
  align-items: flex-start;
}
.fs-body {
  position: relative;
  transform-origin: 50% 100%;
}
.fs-prop.top-anchored .fs-body { transform-origin: 50% 0%; }
.fs-body > img {
  display: block;
  height: var(--h);
  width: auto;
  image-rendering: pixelated;
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}
.fs-prop.flip .fs-body > img { transform: scaleX(-1); }

/* Tappable props get a generous invisible hit area */
.fs-prop.tappable { cursor: pointer; }
.fs-prop.tappable .fs-body::before {
  content: '';
  position: absolute;
  inset: -14px;
  pointer-events: auto;
}
.fs-prop.tappable .fs-body { pointer-events: auto; }
.fs-prop:not(.tappable) .fs-body { pointer-events: none; }

/* Floor-sitting props: feather the bottom edge into the ground so a flat
   cut never shows as a hard seam (safety net on top of the soft-bottomed art) */
.fs-prop.grounded .fs-body > img {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 86%, rgba(0, 0, 0, 0.55) 94%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 86%, rgba(0, 0, 0, 0.55) 94%, transparent 100%);
}

/* ---- Idle motion (ambient life) ---- */
@keyframes fs-sway {
  0%, 100% { transform: rotate(-1.2deg); }
  50%      { transform: rotate(1.2deg); }
}
@keyframes fs-sway-hang {
  0%, 100% { transform: rotate(-2.5deg); }
  50%      { transform: rotate(2.5deg); }
}
@keyframes fs-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2px); }
}
.fs-body.idle-sway { animation: fs-sway var(--dur, 5s) ease-in-out infinite; animation-delay: var(--delay, 0s); }
.fs-body.idle-hang { animation: fs-sway-hang var(--dur, 6s) ease-in-out infinite; animation-delay: var(--delay, 0s); }
.fs-body.idle-bob  { animation: fs-bob var(--dur, 4s) ease-in-out infinite; animation-delay: var(--delay, 0s); }

/* Fern brushing past a plant */
@keyframes fs-brush {
  0%   { transform: rotate(0deg); }
  25%  { transform: rotate(var(--dir, 6deg)) scaleY(0.97); }
  55%  { transform: rotate(calc(var(--dir, 6deg) * -0.5)); }
  80%  { transform: rotate(calc(var(--dir, 6deg) * 0.2)); }
  100% { transform: rotate(0deg); }
}
.fs-body.brush { animation: fs-brush 0.7s ease-out; }

/* ---- Tap reactions ---- */
@keyframes fs-bounce {
  0%   { transform: translateY(0) scale(1, 1); }
  20%  { transform: translateY(3px) scale(1.12, 0.86); }
  50%  { transform: translateY(-16px) scale(0.92, 1.1); }
  72%  { transform: translateY(0) scale(1.05, 0.96); }
  100% { transform: translateY(0) scale(1, 1); }
}
.fs-body.bounce { animation: fs-bounce 0.55s cubic-bezier(0.34, 1.56, 0.64, 1); }

@keyframes fs-rustle {
  0%   { transform: rotate(0deg) scale(1); }
  15%  { transform: rotate(-5deg) scale(1.04, 0.97); }
  35%  { transform: rotate(5deg) scale(0.97, 1.04); }
  55%  { transform: rotate(-3deg); }
  75%  { transform: rotate(2deg); }
  100% { transform: rotate(0deg) scale(1); }
}
.fs-body.rustle { animation: fs-rustle 0.7s ease-out; }

@keyframes fs-wobble {
  0%   { transform: rotate(0); }
  20%  { transform: rotate(-3deg) translateX(-2px); }
  45%  { transform: rotate(3deg) translateX(2px); }
  70%  { transform: rotate(-1.5deg); }
  100% { transform: rotate(0); }
}
.fs-body.wobble { animation: fs-wobble 0.6s ease-out; }

@keyframes fs-knock {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(-4px) rotate(-8deg); }
}
.fs-body.knock { animation: fs-knock 0.18s ease-in-out 3; }

/* Discovery burst */
.fs-burst {
  position: absolute;
  width: 140px;
  height: 140px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 240, 170, 0.75) 0%, rgba(255, 210, 90, 0.3) 40%, transparent 70%);
  animation: fs-burst 0.8s ease-out forwards;
  pointer-events: none;
}
@keyframes fs-burst {
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(0.2); }
  40%  { opacity: 0.85; transform: translate(-50%, -50%) scale(1.2); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.8); }
}

/* Hint sparkle on the next cover */
.fs-hint-sparkle {
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: radial-gradient(circle, #fff8d0 0%, #ffe888 45%, transparent 70%);
  box-shadow: 0 0 10px 3px rgba(255, 232, 136, 0.8);
  pointer-events: none;
  animation: fs-twinkle 1.4s ease-in-out infinite;
}
@keyframes fs-twinkle {
  0%, 100% { opacity: 0; transform: scale(0.4); }
  50%      { opacity: 1; transform: scale(1.2); }
}

/* ---- Creatures spawned by interactions ---- */
.fs-actor {
  position: absolute;
  pointer-events: none;
}
.fs-actor img {
  display: block;
  height: var(--h);
  width: auto;
  image-rendering: pixelated;
  transform-origin: 50% 50%;
  -webkit-user-drag: none;
}
.fs-actor.flip img { transform: scaleX(-1); }

/* Ripples on the pond */
.fs-ripple {
  position: absolute;
  border: 2px solid rgba(240, 255, 250, 0.7);
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0.2);
  animation: fs-ripple 1.3s ease-out forwards;
  pointer-events: none;
}
@keyframes fs-ripple {
  0%   { opacity: 0.9; transform: translate(-50%, -50%) scale(0.2) scaleY(0.4); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.4) scaleY(0.4); }
}

/* Generic particle (spores, petals, moss bits, sparkles) */
.fs-particle {
  position: absolute;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  pointer-events: none;
}
.fs-particle.glow { border-radius: 2px; }

/* ---- Atmosphere overlay: god rays, motes, fireflies ---- */
.fs-atmo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}
.fs-vignette {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(10, 20, 6, 0.35) 0%, rgba(10, 20, 6, 0) 22%),
    radial-gradient(ellipse at 50% 55%, rgba(0, 0, 0, 0) 55%, rgba(6, 12, 4, 0.35) 100%);
}
.fs-mote {
  position: absolute;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: rgba(255, 244, 200, 0.9);
  box-shadow: 0 0 4px rgba(255, 240, 180, 0.8);
  animation: fs-mote-drift var(--dur, 9s) linear infinite;
  animation-delay: var(--delay, 0s);
  opacity: 0;
}
@keyframes fs-mote-drift {
  0%   { opacity: 0; transform: translate(0, 0); }
  15%  { opacity: 0.9; }
  85%  { opacity: 0.6; }
  100% { opacity: 0; transform: translate(var(--dx, 30px), var(--dy, 80px)); }
}
.fs-firefly {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: radial-gradient(circle, #fff8c4 0%, #ffe888 40%, rgba(255, 232, 136, 0.4) 65%, transparent 100%);
  box-shadow: 0 0 10px 3px rgba(255, 232, 136, 0.75);
  animation: fs-firefly-drift var(--dur, 8s) ease-in-out infinite, fs-firefly-blink 2.2s ease-in-out infinite;
  animation-delay: var(--delay, 0s), var(--delay, 0s);
}
@keyframes fs-firefly-drift {
  0%, 100% { transform: translate(0, 0); }
  25%  { transform: translate(var(--dx1), var(--dy1)); }
  50%  { transform: translate(var(--dx2), var(--dy2)); }
  75%  { transform: translate(var(--dx3), var(--dy3)); }
}
@keyframes fs-firefly-blink {
  0%, 100% { opacity: 0.2; }
  50%      { opacity: 1; }
}

/* ---- HUD (outside the scaled stage, uses the game's responsive sizing) ---- */
.fs-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 20;
  width: clamp(36px, 6vw, 48px);
  height: clamp(60px, 12vw, 80px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  color: var(--gold-bright, #ffe888);
  background: rgba(10, 14, 20, 0.45);
  border: 2px solid rgba(218, 186, 106, 0.4);
  cursor: pointer;
  transition: opacity 0.3s ease;
  -webkit-tap-highlight-color: transparent;
  animation: fs-arrow-pulse 2s ease-in-out infinite;
}
.fs-arrow.left  { left: 0.5rem; border-radius: 0 4px 4px 0; }
.fs-arrow.right { right: 0.5rem; border-radius: 4px 0 0 4px; }
.fs-arrow.hidden { opacity: 0; pointer-events: none; }
.fs-arrow:hover, .fs-arrow:active { background: rgba(58, 90, 42, 0.6); border-color: var(--gold, #daba6a); }
/* Pixel-stepped chevron drawn from the button's colour (no font glyph) */
.fs-chevron {
  display: block;
  width: 42%;
  height: 40%;
  background: currentColor;
  clip-path: polygon(0 0, 40% 0, 60% 20%, 80% 40%, 100% 50%, 80% 60%, 60% 80%, 40% 100%, 0 100%, 20% 80%, 40% 60%, 50% 50%, 40% 40%, 20% 20%);
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.7));
}
.fs-arrow.left .fs-chevron { transform: scaleX(-1); }

/* Music notes (birdbox): inline pixel-art SVG sprites */
.fs-note {
  position: absolute;
  width: 16px;
  height: 24px;
  transform: translate(-50%, -50%);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 12' shape-rendering='crispEdges'%3E%3Cpath fill='%23ffe888' d='M5 0h1v9H5zM6 1h1v1H6zM7 2h1v2H7zM3 8h3v1H3zM2 9h4v1H2zM2 10h3v1H2z'/%3E%3C/svg%3E") center / contain no-repeat;
  image-rendering: pixelated;
  filter: drop-shadow(0 0 1px #000) drop-shadow(0 1px 0 rgba(0, 0, 0, 0.8));
  pointer-events: none;
}
.fs-note-double {
  width: 24px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' shape-rendering='crispEdges'%3E%3Cpath fill='%23ffe888' d='M4 0h7v2H4zM4 2h1v7H4zM10 2h1v7h-1zM2 8h3v1H2zM1 9h4v1H1zM1 10h3v1H1zM8 8h3v1H8zM7 9h4v1H7zM7 10h3v1H7z'/%3E%3C/svg%3E");
}
@keyframes fs-arrow-pulse { 0%, 100% { opacity: 0.65; } 50% { opacity: 1; } }


