/* ===========================================================================
   Brunnslockspoesi — layout, components & animations
   Structure: reset → stage → button base (reused) → variants → positions →
   states/animations. Repeating design lives in shared rules, never per-button.
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html, body { height: 100%; margin: 0; }

body {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  background: radial-gradient(circle at 50% 30%, #cfcec6, #bfbeb5);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  overflow: hidden;
}

/* --- Stage wrap: reserves the *scaled* footprint so the app is always fully
   visible and correctly centered (the scaled .stage keeps its ratio) -------- */
.stage-wrap {
  position: relative;
  width: calc(var(--stage-w) * var(--stage-scale, 1));
  height: calc(var(--stage-h) * var(--stage-scale, 1));
}

/* --- Stage: the 402x874 design canvas, scaled to fit the viewport ---------- */
.stage {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--stage-w);
  height: var(--stage-h);
  background: var(--beige);
  border-radius: 28px;
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.35);
  /* Scale to fit while keeping pixel-perfect proportions */
  transform: scale(var(--stage-scale, 1));
  transform-origin: top left;
}

/* Phones: drop the card, go edge-to-edge beige, scale to fill nicely --------- */
@media (max-width: 640px) {
  body { background: var(--beige); }
  .stage {
    border-radius: 0;
    box-shadow: none;
  }
}

/* --- Button base (shared by every control) --------------------------------- */
.btn {
  position: absolute;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
  transition:
    transform var(--t-fast) var(--ease-spring),
    box-shadow var(--t-med) var(--ease-out),
    background-color var(--t-med) var(--ease-out),
    filter var(--t-med) var(--ease-out);
  will-change: transform;
}
.btn:focus-visible {
  outline: 3px solid rgba(0, 0, 0, 0.45);
  outline-offset: 4px;
}
.btn:hover { transform: scale(1.05); }
.btn:active { transform: scale(0.94); }

/* Icon sizing inside buttons */
.btn svg { display: block; width: 55%; height: 55%; pointer-events: none; }

/* --- Round-button shared shape --------------------------------------------- */
.btn--big,
.btn--slot,
.btn--random {
  border-radius: 50%;
  box-shadow:
    0 10px 22px -8px rgba(0, 0, 0, 0.4),
    inset 0 -6px 14px -6px rgba(0, 0, 0, 0.25),
    inset 0 4px 10px -4px rgba(255, 255, 255, 0.35);
}

/* --- Variants -------------------------------------------------------------- */
.btn--big {
  width: var(--big-size);
  height: var(--big-size);
  background: var(--big-color);
}
/* The big button uses the beat animation for feedback, so its resting size
   must equal the animation's start/end frame (scale 1). Keep hover/press as
   shadow-only — no transform — so nothing to snap back to when beat ends. */
.btn--big:hover { box-shadow: 0 18px 40px -12px rgba(0, 0, 0, 0.5); transform: none; }
.btn--big:active { transform: none; }

.btn--slot { width: var(--slot-size); height: var(--slot-size); }
.pos-green  { background: var(--green); }
.pos-blue   { background: var(--blue); }
.pos-yellow { background: var(--yellow); }
.pos-purple { background: var(--purple); }
.pos-red    { background: var(--red); }

.btn--random {
  width: var(--slot-size);
  height: var(--slot-size);
  background: var(--orange);
  color: var(--icon-clover);
}

.btn--save {
  width: var(--save-w);
  height: var(--save-h);
  background: var(--gray);
  color: var(--icon-heart);
  border-radius: 44px / 52px;
  box-shadow:
    0 10px 22px -8px rgba(0, 0, 0, 0.4),
    inset 0 -6px 14px -6px rgba(0, 0, 0, 0.22),
    inset 0 4px 10px -4px rgba(255, 255, 255, 0.35);
}

/* --- Positions (top-left px, from Figma; symmetrical around x=201) ---------- */
.pos-big    { left: 61px;  top: 102px; }
.pos-green  { left: 156px; top: 462px; }
.pos-blue   { left: 60px;  top: 516px; }
.pos-yellow { left: 252px; top: 516px; }
.pos-purple { left: 60px;  top: 627px; }
.pos-red    { left: 252px; top: 627px; }
.pos-random { left: 156px; top: 572px; }
.pos-save   { left: 156px; top: 682px; }

/* ===========================================================================
   States & animations
   ========================================================================== */

/* Entrance — buttons pop in, staggered via --enter-delay set in JS */
@keyframes pop-in {
  0%   { opacity: 0; transform: scale(0.2); }
  60%  { opacity: 1; transform: scale(1.08); }
  100% { opacity: 1; transform: scale(1); }
}
.stage.enter .btn {
  opacity: 0;
  animation: pop-in var(--t-slow) var(--ease-spring) forwards;
  animation-delay: var(--enter-delay, 0ms);
}

/* While a fanfare is sounding — a soft breathing glow in the big button's own
   color. Shadow-only, so nothing snaps when it stops mid-cycle. */
.btn--big.is-sounding { animation: sounding 1.1s ease-in-out infinite; }
@keyframes sounding {
  0%, 100% {
    box-shadow:
      0 10px 22px -8px rgba(0, 0, 0, 0.4),
      0 0 0 0 var(--big-color);
  }
  50% {
    box-shadow:
      0 12px 26px -8px rgba(0, 0, 0, 0.45),
      0 0 26px 5px var(--big-color);
  }
}

/* Big button "play" — ripple ring + a springy beat ------------------------- */
.btn__ripple {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  box-shadow: 0 0 0 0 var(--big-color);
  opacity: 0;
}
.btn--big.is-playing { animation: beat 620ms var(--ease-out) forwards; }
.btn--big.is-playing .btn__ripple { animation: ripple 620ms var(--ease-out); }
/* Overshoot lives in the middle; the tail eases gently back to 1 so there is
   no snap when the animation ends. */
@keyframes beat {
  0%   { transform: scale(1); }
  22%  { transform: scale(1.08); }
  46%  { transform: scale(0.975); }
  70%  { transform: scale(1.02); }
  100% { transform: scale(1); }
}
@keyframes ripple {
  0%   { opacity: 0.55; box-shadow: 0 0 0 0 var(--big-color); }
  100% { opacity: 0; box-shadow: 0 0 0 46px transparent; }
}

/* Big button color-swap flash when a slot is loaded ------------------------ */
.btn--big.is-swapping { animation: swap-flash 420ms var(--ease-out); }
@keyframes swap-flash {
  0%   { transform: scale(1); filter: brightness(1); }
  40%  { transform: scale(1.05); filter: brightness(1.18); }
  100% { transform: scale(1); filter: brightness(1); }
}

/* Randomise — flower spins 3 full turns over 3s with a quick pop at the start */
.btn--random.is-spinning { animation: shuffle 3s var(--ease-out); }
.btn--random.is-spinning svg { animation: spin 3s cubic-bezier(0.45, 0.05, 0.2, 1); }
@keyframes spin { from { transform: rotate(0); } to { transform: rotate(1080deg); } }
@keyframes shuffle {
  0%   { transform: scale(1); }
  8%   { transform: scale(1.12); }
  20%  { transform: scale(1); }
  100% { transform: scale(1); }
}

/* Heart — beats on toggle, stays "armed" while in save mode ----------------- */
.btn--save.is-beating { animation: heart-beat 480ms var(--ease-spring); }
@keyframes heart-beat {
  0%, 100% { transform: scale(1); }
  25%      { transform: scale(1.16); }
  50%      { transform: scale(0.98); }
  75%      { transform: scale(1.08); }
}
.stage.save-mode .btn--save {
  filter: brightness(1.06);
  box-shadow:
    0 0 0 4px rgba(43, 46, 51, 0.18),
    0 10px 22px -8px rgba(0, 0, 0, 0.4);
}

/* Save mode — the five slots pulsate in a wave, one pulse over 2s, each slot
   offset by --pulse-delay so purple leads and blue/green/yellow/red follow. */
.stage.save-mode .btn--slot {
  animation: pulse 1s ease-in-out infinite;
  animation-delay: var(--pulse-delay, 0ms);
  cursor: copy;
}
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.1); }
}

/* Slot save confirmation — a satisfying pop + ring ------------------------- */
.btn--slot.is-saved { animation: saved-pop 560ms var(--ease-spring); }
@keyframes saved-pop {
  0%   { transform: scale(1); box-shadow: 0 0 0 0 rgba(255,255,255,0.8); }
  40%  { transform: scale(1.25); box-shadow: 0 0 0 10px rgba(255,255,255,0); }
  100% { transform: scale(1); box-shadow: 0 10px 22px -8px rgba(0,0,0,0.4); }
}

@media (prefers-reduced-motion: reduce) {
  .btn, .btn * { animation: none !important; transition: none !important; }
}
